Skip to content

Harden credential storage, diagnostics, and generated bundles - #860

Open
mconflitti-pbc wants to merge 1 commit into
horse-cockroach-43481edafrom
security-hardening-agent-workflows
Open

mconflitti-pbc wants to merge 1 commit into
horse-cockroach-43481edafrom
security-hardening-agent-workflows

Conversation

@mconflitti-pbc

@mconflitti-pbc mconflitti-pbc commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Intent

Reduce accidental credential exposure in saved files, authentication diagnostics, and generated deployment artifacts. This PR contains only the deferred /tmp/rsconnect-security-hardening.patch; it builds on #859 and targets that feature branch so the review diff excludes resumable login and preflight implementation.

Type of Change

  • Bug Fix
  • New Feature
  • Breaking Change

The security protections intentionally change the edge cases described below. They are separate from the additive feature and are not a prerequisite for merging #859.

Approach

  • Default credential-file saves write through a private temporary file, flush and fsync it, then atomically replace the destination. Unchanged regular files have their permissions repaired. Tests cover failures, cleanup, fallback locations, and trusted custom openers.
  • OAuth diagnostics omit provider descriptions, response bodies/header values, and redirect destinations. Ordinary HTTP diagnostics redact encoded credential query/fragment names and omit response reasons, raw transport details, and cookie names. Requests, routing, token checkpoints, and retry behavior retain their contracts.
  • Generated bundles and manifests exclude .rsconnect-python and the active CLI configuration directory, including explicit extras and resolved symlink aliases. Publishing from inside the configuration directory is rejected; static notebooks are rejected before execution. Tests cover Python, Node.js, notebook, Quarto, and manifest paths.

Compatibility effects: credential updates require a writable parent directory; destination symlinks are replaced rather than followed, and hardlink aliases retain old contents. Human-readable diagnostics are less detailed. Configuration files can no longer be explicitly forced into generated deployment artifacts. Trusted custom I/O callbacks retain their existing direct-write behavior; prepared archives are uploaded unchanged.

Pending credentials remain plaintext accessible to the same operating-system user, root, and backups. This does not add token revocation or general credential scanning of application files or prepared archives. The POSIX-only boundary of the new workflows remains unchanged; no native Windows security helpers are introduced.

Automated Tests

  • Full isolated Python 3.13 suite: 1,647 passed, 14 skipped, 818 subtests passed, including real CLI subprocess integration tests against local HTTP/OAuth fixtures.
  • Python 3.8 affected security/compatibility gate: 1,012 passed, 2 skipped.
  • Ruff lint/format, whitespace checks, and strict Pyright for the resumable-login/preflight modules pass.
  • Wheel build passes; all 36 packaged Python modules match the branch sources. Documentation build passes with two existing missing-anchor notices.
  • Patch application was verified against all 317 saved target file hashes; the PR changes exactly the patch's 19 files.

Tests use temporary HOME/configuration directories and synthetic credentials. Subprocess integration tests exercise the actual CLI against local HTTP/OAuth fixtures, including pending-login files inside application content, errors that echo secrets, resumed token flows, and static-notebook rejection before execution or upload.

Directions for Reviewers

Review the diff against horse-cockroach-43481eda, especially metadata.py atomic replacement, http_support.py/oauth.py diagnostic suppression, and bundle.py path filtering. Confirm the intentional compatibility effects are acceptable before merging. The parent #859 preserves existing server aliases, public missing-account exception types, and direct Click callback behavior; those fixes remain in this branch.

Independent Luna review — remaining findings:

  • Existing general API error handling still includes server-supplied error text in exceptions (api.py, AbstractRemoteServer.handle_bad_response), so a server that echoes credentials can expose them through those messages.
  • Existing OAuth discovery failures still include the configured URL verbatim (oauth.py, discover_oauth_metadata); credential-bearing query parameters in that URL can appear in errors.
  • The patch removes scoped logging keyword arguments introduced in Add resumable device login and Python/Node.js preflight #859 (suppress_response_logging and CookieJar.suppress_logs). There are no remaining repository callers, but external callers using those new keywords would receive TypeError.
  • Bundle filtering covers configuration paths and resolved symlink aliases, not a hardlink to a credential file copied under an ordinary application filename.

These are recorded rather than extending the saved patch. This PR is targeted hardening, not a guarantee of complete credential suppression. The existing Quarto manifest function increases from CC 11 to 12 due to its file guard; new helpers meet the cyclomatic complexity limit.

This PR depends on #859. Retarget/rebase after the parent merges if the repository's merge workflow requires it.

Checklist

  • I have updated CHANGELOG.md to cover notable changes.
  • I have updated all related GitHub issues to reflect their current state.
  • I have run the rsconnect-python-tests-at-night workflow in Connect against this feature branch.

Live Connect and native Windows execution have not been validated locally.

Keep the deferred security changes separate from the additive agent
workflows. Protect default credential writes with private atomic
replacement, suppress sensitive auth diagnostics, and exclude CLI
configuration from generated manifests and bundles.

BREAKING CHANGE: saves require a writable parent, replace destination
symlinks, and leave hardlink aliases unchanged. Diagnostics provide
less detail and configuration files cannot be forced into bundles.
Trusted custom openers and prepared archives keep existing behavior.

Refs #859
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://posit-dev.github.io/rsconnect-python/pr-preview/pr-860/

Built to branch gh-pages at 2026-10-08 21:12 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant