Security architecture and threat model

This document is the authoritative reviewer-facing security model for Copy GitHub Repository. It consolidates protected assets, trust assumptions, threat classes, controls, evidence, and residual risk without replacing the behavioral contract in product-contract.md, the architecture in architecture.md, the quality evidence model in quality-strategy.md, or the installation trust authority in installation-security.md.

SECURITY.md remains the vulnerability-reporting and supported-security-version front door.

Security objectives

The project is designed to:

  • preserve the operator-approved source state rather than silently substituting newer state;
  • prevent accidental overwrite/deletion of existing repositories;
  • preserve repository identity and recovery evidence across replacement failures;
  • avoid shell-string command execution and unnecessary credential exposure;
  • fail closed when required host, identity, state, permission, or verification assumptions are not satisfied;
  • make security-relevant evidence and residual risk auditable without overstating unimplemented controls.

Protected assets

Asset Security concern
Source repository identity and approved content state substitution, TOCTOU drift, unauthorized mutation
Destination/archive repository identity overwrite, identity confusion, loss of recovery path
GitHub CLI authentication material disclosure, unintended reuse, logging
Repository settings/protection state accidental weakening or incorrect restoration
Local temporary workspaces tampering, stale/malformed content, resource failure
Recovery/provenance reports integrity, accidental sensitive-data disclosure
Release ZIP/checksum, SBOM, provenance attestations, and future signing evidence artifact substitution, publication compromise
Development/CI dependencies and workflow definitions supply-chain compromise

Actors and trust assumptions

  • Operator / automation supplies intent, repository names, confirmation, local report destinations, and access through an already authenticated GitHub CLI context.
  • CopyGitHubRepo module is trusted to enforce the product contract, safety checks, execution ordering, verification, and evidence semantics.
  • PowerShell runtime is trusted to load and execute the module and helper scripts.
  • Git, Git LFS, and GitHub CLI are external native prerequisites whose executables and behavior are outside the module’s direct control.
  • GitHub.com is the supported remote platform for v0.1.0. API and Git transport availability, authorization, repository identity, and platform-side mutation are external trust dependencies.
  • GitHub Actions / release environment is trusted for CI and release automation subject to repository permissions, workflow integrity, and configured secrets/environments.
  • PowerShell Gallery and GitHub Releases are distribution services, not runtime dependencies of an installed module.

The project does not assume repository names are immutable identities. GitHub repository IDs/node IDs are used where available for identity-sensitive replacement checks.

Trust boundaries and sensitive-data flow

flowchart LR
    Operator[Operator / automation]
    Module[CopyGitHubRepo]
    GHCLI[GitHub CLI auth context]
    Native[Git / Git LFS / gh]
    GitHub[GitHub.com APIs and Git transport]
    Local[Temporary workspace / reports]
    Release[GitHub Actions / Releases / PSGallery]

    Operator --> Module
    GHCLI --> Native
    Module --> Native
    Native --> GitHub
    Module --> GitHub
    Module --> Local
    Release --> Operator

Credential/data rules:

  • The module uses existing GitHub CLI authentication and does not intentionally collect, display, copy, or persist token values.
  • HTTPS Git operations use GitHub CLI credentials through command-scoped Git configuration; interactive credential prompting is disabled.
  • GitHub secrets, webhook secrets, private deploy-key material, GitHub App credentials, environment secrets, and similar secret-bearing configuration are outside the repository-copy contract.
  • Normal results/recovery evidence may contain repository names, immutable repository IDs, commit/tree SHAs, mode, completed stages, failure stage, and verification/provenance evidence.
  • Tokens, secret values, private keys, and unrelated private repository content must not be written intentionally to console output, reports, diagnostics, or CI artifacts.
  • Diagnostic output is still a security boundary: future logging changes must be reviewed for credential and sensitive-content leakage.

Privileged and destructive operations

Security-sensitive mutations include:

  1. archive/rename of an existing destination or same-name source;
  2. destination/replacement repository creation;
  3. Git content and LFS publication;
  4. repository settings restoration;
  5. repository protection restoration;
  6. release/package publication by maintainer workflows.

Planning, -PlanOnly, and -WhatIf remain non-mutating. Before the first GitHub mutation, the application revalidates the immutable approved source state. Exact replacement confirmation and ShouldProcess boundaries are part of the authorization model; same-name destructive confirmation is not bypassed by ordinary confirmation suppression.

After a post-mutation failure, the product preserves known repositories and recovery evidence. It does not automatically delete repositories or rename archives back.

Threat and failure model

Threat / failure class Primary security effect Current mitigation / behavior
Shell/command injection arbitrary local command execution centralized native-process helpers, discrete argument lists, custom security analyzer rules, engineering prohibition on shell-string evaluation / Invoke-Expression
Stale-state substitution / TOCTOU operator approves one source state but another is copied immutable SourceState, pre-mutation revalidation, workspace revalidation, fail-closed SourceStateChangedSincePlanning
Destination overwrite / destructive confusion loss of existing repository archive-before-replace, exact confirmation, immutable identity checks, distinct replacement identity
Repository-name identity confusion wrong repository accepted after rename/recreate immutable GitHub repository identity continuity where available
Credential leakage token compromise existing GitHub CLI auth context, no intentional token persistence/display, command-scoped credential configuration, analyzer detection for direct emission of secret-bearing variables
Malformed or adversarial remote state unsafe execution or incorrect verification validation/normalization, explicit supported-host boundary, approved-plan evidence, destination read-back verification
Native prerequisite compromise arbitrary behavior below module boundary documented prerequisite/trust boundary; centralized invocation and static boundary enforcement reduce but do not eliminate risk
Network/API interruption or throttling incomplete operation / partial mutation bounded retry for recognized side-effect-free GitHub API reads; mutation calls are not automatically replayed; preservation/recovery semantics apply
Local disk/temp resource failure interrupted copy/evidence loss observed-workspace preflight can reject a defensible shortage before mutation; later exhaustion follows preservation-first recovery semantics
Partial mutation archive/destination may exist after failure explicit completed-stage/recovery evidence; no automatic rollback/delete
Settings/protection restoration failure verified content with incomplete configuration content verifies first, settings then protection; failure is reported as a distinct late mutation state
Release artifact substitution user installs unintended bytes SHA-256 integrity comparison plus GitHub build-provenance attestation bound to the release ZIP, expected repository, signer workflow, and source commit; Authenticode remains a separate optional control
Dependency/workflow compromise CI/release or development environment compromise exact dependency/action pinning, reviewed development dependency versions, dedicated PowerShell security analysis, CodeQL analysis of GitHub Actions workflows, dependency monitoring, and repository-security baseline verification
Persistent PSGallery trust mutation during dev setup workstation trust posture altered development dependency installer targets PSGallery explicitly without changing repository InstallationPolicy; regression is protected by DevelopmentDependencies.Tests.ps1

Security control and evidence matrix

Status vocabulary:

  • Implemented — enforced in repository code/configuration.
  • Automatically verified — protected by tests/analyzers/workflows.
  • Platform-provided / live verification required — depends on live GitHub/repository configuration and must not be inferred from source alone.
  • Planned / open — a documented control is not yet implemented or satisfied.
  • Residual risk — risk that remains after current controls.
Control Purpose Current implementation / authority Evidence Status
Approved immutable source state TOCTOU/substitution defense planning + approved-plan execution + workspace checks ApprovedSourceState.Tests.ps1, StaleStateSafety.Tests.ps1, architecture fitness functions Implemented + automatically verified
Archive-before-replace and identity continuity destructive-operation safety replacement orchestration/product contract replacement/same-name integration tests and E2E harnesses Implemented + automatically verified; live evidence remains release-specific
Distinct replacement identity prevents renamed repository from masquerading as replacement immutable repository ID checks where available same-name/replacement tests Implemented + automatically verified
No automatic rollback/delete preservation and forensic/recovery safety recovery/result contract recovery/risk-failure tests Implemented + automatically verified
Centralized native process invocation command-injection/quoting boundary process helpers using argument lists/no shell evaluation native-command tests + analyzer contracts Implemented + automatically verified
Credential minimization reduce token exposure existing gh auth, command-scoped helper, no intentional token persistence/output security/documentation contracts and implementation review Implemented; not a guarantee against compromised prerequisites
GitHub.com-only host guard prevents unvalidated host semantics explicit fail-closed host checks HostName.Tests.ps1 Implemented + automatically verified
Content-before-settings/protection ordering prevents protection from blocking initial publication and makes late failure explicit application orchestration settings/protection tests Implemented + automatically verified
Release ZIP SHA-256 check integrity/corruption detection stable installer/release contract installation-security and release contract tests Implemented; checksum alone does not authenticate publisher
Development dependency version review reduce stale development-tool risk exact pins in build/DevelopmentDependencies.psd1 cross-platform project-quality validation and upstream release/advisory review Implemented + automatically verified for selected pins
Dedicated PowerShell code security analysis expose PowerShell-specific security failures separately from general quality .github/workflows/analyze-code-security.yml using PSScriptAnalyzerSecuritySettings.psd1, Measure-CgrSecurity, selected built-in rules, and targeted Pester evidence CodeSecurityWorkflow.Tests.ps1, PSScriptAnalyzerSecurityRules.Tests.ps1, safety/recovery tests Implemented + automatically verified when the dedicated workflow passes
CodeQL for GitHub Actions workflow-code static analysis .github/workflows/analyze-github-actions-security.yml, language actions, security-extended queries CodeQLWorkflow.Tests.ps1 + successful live CodeQL workflow execution Implemented + automatically verified for GitHub Actions workflows; does not scan PowerShell source
Automated dependency/supply-chain monitoring outdated/vulnerable dependency visibility .github/dependabot.yml, .github/workflows/monitor-dependencies.yml, dependency-monitoring.md DevelopmentDependencies.Tests.ps1 + scheduled/manual workflow contract Implemented + automatically verified
Live GitHub security-setting baseline secret scanning, push protection, Dependabot/code scanning settings and main-branch ruleset expectations repository-security-baseline.md live repository settings and owner-side verification Platform-provided / live verification required; required v0.1.0 baseline restored and verified during release qualification
Independent release authenticity/signing authenticate release artifact origin beyond an adjacent checksum GitHub artifact attestations produced by .github/workflows/publish-release.yml and verified against repository/workflow/source identity release workflow attestation records, install-release.ps1, installation-security.md Implemented for v0.1.0 with GitHub artifact attestations; Authenticode publisher signing remains optional/not implemented
PSGallery trust-policy preservation avoid persistent development-host trust mutation dependency installer does not call Set-PSRepository; exact versions are installed from explicit PSGallery source DevelopmentDependencies.Tests.ps1, cross-platform project-quality validation Implemented + automatically verified
SBOM / provenance evidence component/release assurance build/New-ReleaseSbom.ps1, .github/workflows/publish-release.yml, release-sbom.md ReleaseSbom.Tests.ps1, release workflow contracts, cross-platform project-quality evidence Implemented + automatically verified

Release SBOM and provenance evidence

Stable release automation generates SPDX 2.3 JSON from the completed deterministic release ZIP rather than from an unrelated mutable source tree. build/New-ReleaseSbom.ps1 records the exact shipped file inventory, SHA-256 file and artifact checksums, package/version identity, source commit, deterministic creation metadata, and the SPDX 2.x package verification code required by that format.

The stable publication workflow publishes the .spdx.json sidecar and uses immutable-pinned actions/attest steps for build provenance and SBOM attestation of the same versioned ZIP. Required attestation failures fail publication before PowerShell Gallery or GitHub Release publication. See release-sbom.md for retrieval, verification, classification, and reproducibility details.

For v0.1.0, GitHub artifact attestation is the selected independent release-authenticity mechanism. Verification binds the artifact digest to the expected repository, publish-release.yml signer workflow, and exact release source commit. This is independent of trusting the adjacent .sha256 file, but it is not Authenticode publisher signing and does not use a separately managed project private signing key. It also does not prove vulnerability absence or make semantic SBOM classification infallible.

Dependency and trust inventory

Class Current dependency / service Security posture
Runtime platform PowerShell 7.4+ external prerequisite
Runtime native prerequisite Git external executable/trust boundary
Runtime native prerequisite GitHub CLI authentication/API prerequisite
Conditional runtime prerequisite Git LFS required for FullHistory and Snapshot with approved LFS content
Runtime PowerShell modules none declared by the module manifest no third-party PowerShell runtime dependency currently shipped
Development modules Pester 6.1.0, PSScriptAnalyzer 1.25.0 exact-version pinned; weekly freshness/advisory monitoring is documented in dependency-monitoring.md
CI actions GitHub Actions referenced by workflows immutable SHA pinning is repository policy; Dependabot proposes reviewed updates and CodeQL analyzes workflow code
Runtime remote service GitHub.com v0.1.0 supported host and primary external service
Distribution GitHub Releases, PowerShell Gallery release/distribution trust boundaries; not installed-module runtime dependencies

Security static-analysis policy

PowerShell code security and GitHub Actions security use separate analysis surfaces because CodeQL does not analyze the project’s PowerShell source.

PowerShell code security

PSScriptAnalyzerSecuritySettings.psd1 is the dedicated security profile. It intentionally selects a small set of high-signal built-in PSScriptAnalyzer rules plus the repository-owned Measure-CgrSecurity custom rule. The custom rule targets high-confidence patterns in production and operational PowerShell:

  • Invoke-Expression / iex dynamic evaluation;
  • explicit cmd /c, sh -c, bash -c, or zsh -c shell interpretation;
  • direct git, gh, or git-lfs invocation from module source that bypasses the centralized native-process boundary;
  • direct output/diagnostic emission of variables whose names indicate token, password, secret, credential, private-key, API-key, or authentication material.

.github/workflows/analyze-code-security.yml runs that profile and targeted Pester evidence for security-sensitive behavior including host restrictions, source-state drift, replacement confirmation, retry/mutation rules, recovery evidence, and analyzer detections. PSScriptAnalyzerSecurityRules.Tests.ps1 verifies positive detections and safe cases.

This dedicated gate is intentionally not a second copy of the general project-quality workflow. The general PSScriptAnalyzerSettings.psd1 path continues to apply broader quality/style analysis; the security workflow gives the smaller security policy and security-sensitive behavioral evidence a distinct required-check surface.

The policy intentionally avoids speculative heuristics that would create routine false positives. A clean analyzer result therefore means the defined high-confidence patterns were not found; it does not mean arbitrary PowerShell vulnerabilities cannot exist.

Run the broader repository policy locally through the canonical project gate:

./build/Test-Project.ps1

For focused contract verification of the security analyzer’s positive detections and safe cases, run:

./build/Test-Project.ps1 -Category Contract

GitHub Actions CodeQL policy

The repository uses .github/workflows/analyze-github-actions-security.yml to analyze GitHub Actions workflow code with CodeQL’s actions language and security-extended query suite. The workflow runs when workflow definitions change on main or in pull requests targeting main, on a weekly schedule, and by manual dispatch. Third-party actions are pinned to immutable commit SHAs, checkout does not persist credentials, and the analysis job declares only the permissions required to read repository/action metadata and upload code-scanning results.

The initial CodeQL workflow execution completed successfully. Repository contract tests verify the trigger scope, immutable pins, least-privilege permissions, language actions, query suite, and absence of pull_request_target.

This CodeQL control is intentionally scoped to GitHub Actions workflow code. It does not analyze the project’s PowerShell source. A successful CodeQL run means the configured GitHub Actions analysis completed successfully; it is not proof that all workflow or product vulnerabilities are absent.

Security verification strategy and limits

Current verification combines:

  • Pester Unit/Integration/Contract suites for safety semantics and failure behavior;
  • the dedicated PowerShell security workflow and PSScriptAnalyzerSecuritySettings.psd1;
  • the broader repository-owned PSScriptAnalyzer policy, including the custom Measure-CgrSecurity rule;
  • CodeQL analysis of GitHub Actions workflow code;
  • workflow/package/documentation contract testing;
  • controlled E2E harnesses for selected live GitHub behaviors;
  • manual/live verification where platform configuration cannot be proved from repository files.

These mechanisms are not comprehensive SAST. PowerShell source is not covered by a CodeQL language analysis in this project; GitHub Actions workflow code is covered separately by CodeQL. A passing security gate, project-quality gate, and CodeQL run are strong conformance evidence for the checks that exist; they are not proof that the software is vulnerability-free.

E2E-capable also does not mean a specific release candidate was live-validated. Exact-release-candidate evidence is governed by quality-strategy.md and the release-readiness process.

Privacy and telemetry posture

The project does not define a telemetry/analytics subsystem. It operates on operator-selected GitHub repositories and local paths using the operator’s authenticated GitHub context. It does not intentionally transmit usage analytics to the project maintainer.

Repository content necessarily crosses Git/GitHub transport boundaries as part of the requested copy operation. Local reports/recovery artifacts remain operator-controlled files. Future telemetry, crash reporting, or centralized diagnostics would be a material product/security/privacy change and would require explicit design and documentation rather than being added implicitly.

Residual risk and open hardening

The following remain explicit for release review:

  • live repository security settings are platform-provided state and must be reverified for future release candidates when configuration may have changed;
  • Authenticode publisher signing is not implemented; v0.1.0 instead uses GitHub artifact attestations as its independent authenticity mechanism;
  • native prerequisite compromise (PowerShell, Git, Git LFS, GitHub CLI) remains outside the module’s direct enforcement boundary;
  • GitHub.com availability, authorization, API behavior, and remote-side consistency are external dependencies;
  • no static-analysis combination is proof of vulnerability absence;
  • exact release-candidate live evidence remains separate from deterministic CI capability.

Reporting and incident response

Suspected vulnerabilities should follow SECURITY.md, not public disclosure. Serious post-publication security, credential, supply-chain, artifact, or distribution incidents use incident-response.md.

Preservation principles apply throughout incident handling: retain exact affected version/commit/artifact identities and relevant non-secret evidence; do not silently overwrite immutable release evidence or destroy repository recovery state.