Skip to content

feat: add code agent scaffold, image, and push pipeline - #286

Merged
ascerra merged 2 commits into
fullsend-ai:mainfrom
ascerra:feat/code-agent-scaffold
Apr 21, 2026
Merged

feat: add code agent scaffold, image, and push pipeline#286
ascerra merged 2 commits into
fullsend-ai:mainfrom
ascerra:feat/code-agent-scaffold

Conversation

@ascerra

@ascerra ascerra commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Integrate the proven code-agent configuration into the fullsend installer scaffold so that fullsend install sets up a fully working code agent with bot-authored PRs in any target org.

New scaffold files (internal/scaffold/fullsend-repo/):

  • agents/code.md — agent definition with disallowed tools
  • env/code-agent.env — sandbox environment (git identity, SSL, timeouts)
  • harness/code.yaml — harness config with pre/post scripts and runner_env
  • policies/code.yaml — network policy (Vertex AI, GitHub, registries)
  • scripts/pre-code.sh — input validation before sandbox creation
  • scripts/post-code.sh — secret scan, pre-commit, push, and PR creation
  • scripts/scan-secrets — gitleaks wrapper with SHA256 self-bootstrap
  • skills/code-implementation/SKILL.md — 10-step implementation procedure

Updated scaffold files:

  • .github/workflows/code.yml — uses installer-provisioned GitHub App token (FULLSEND_CODER_APP_ID / FULLSEND_CODER_APP_PRIVATE_KEY), scoped to the target repo for push access

New image build pipeline:

  • .github/workflows/build-images.yml — builds sandbox base then agent images on push to main or manual dispatch, publishes to GHCR
  • images/code/Containerfile — extends base sandbox with Go, gitleaks, pre-commit, gitlint, and scan-secrets

Tests updated for 22 scaffold files (was 14).

Made-with: Cursor

Integrate the proven code-agent configuration into the fullsend
installer scaffold so that `fullsend install` sets up a fully working
code agent with bot-authored PRs in any target org.

New scaffold files (internal/scaffold/fullsend-repo/):
- agents/code.md — agent definition with disallowed tools
- env/code-agent.env — sandbox environment (git identity, SSL, timeouts)
- harness/code.yaml — harness config with pre/post scripts and runner_env
- policies/code.yaml — network policy (Vertex AI, GitHub, registries)
- scripts/pre-code.sh — input validation before sandbox creation
- scripts/post-code.sh — secret scan, pre-commit, push, and PR creation
- scripts/scan-secrets — gitleaks wrapper with SHA256 self-bootstrap
- skills/code-implementation/SKILL.md — 10-step implementation procedure

Updated scaffold files:
- .github/workflows/code.yml — uses installer-provisioned GitHub App
  token (FULLSEND_CODER_APP_ID / FULLSEND_CODER_APP_PRIVATE_KEY),
  scoped to the target repo for push access

New image build pipeline:
- .github/workflows/build-images.yml — builds sandbox base then agent
  images on push to main or manual dispatch, publishes to GHCR
- images/code/Containerfile — extends base sandbox with Go, gitleaks,
  pre-commit, gitlint, and scan-secrets

Tests updated for 22 scaffold files (was 14).

Made-with: Cursor
@github-actions

github-actions Bot commented Apr 20, 2026

Copy link
Copy Markdown

Site preview

Preview: https://58d08299-site.fullsend-ai.workers.dev

Commit: 9e160184111f37d9eeb4a8b811cbfc3c35312e52

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-Agent Review: 4 reviewers (Claude Security, Claude Architecture, Gemini, Cursor)

17 inline findings — 4 critical/must-fix, 2 high, 9 medium, 7 low/info.

Must Fix Before Merge

  1. Token isolation broken — same GitHub App token in sandbox (GH_TOKEN) and runner (PUSH_TOKEN); node binary can bypass disallowedTools via raw HTTP to api.github.com
  2. .pre-commit-config.yaml not in protected paths — agent can inject malicious hooks that execute on the runner with PUSH_TOKEN
  3. Hardcoded main branch — breaks repos with different default branches
  4. GitHub Actions outdateddocker/build-push-action (v6→v7), docker/login-action (v3→v4), docker/metadata-action (v5→v6), docker/setup-buildx-action (v3→v4)

Positive

  • Defense-in-depth architecture is strong overall
  • SHA256 supply chain pinning for Go and gitleaks is solid
  • Zero-trust agent principle well-implemented
  • SKILL.md is comprehensive and internally non-contradictory

Full review documents: see Research/fullsend-pr286-code-agent-scaffold-review-summary.md

Comment thread internal/scaffold/fullsend-repo/scripts/post-code.sh
Comment thread internal/scaffold/fullsend-repo/scripts/post-code.sh Outdated
Comment thread internal/scaffold/fullsend-repo/scripts/post-code.sh Outdated
Comment thread internal/scaffold/fullsend-repo/.github/workflows/code.yml Outdated
Comment thread internal/scaffold/fullsend-repo/scripts/post-code.sh Outdated
Comment thread .github/workflows/build-images.yml Outdated
Comment thread internal/scaffold/fullsend-repo/scripts/pre-code.sh
Comment thread images/code/Containerfile
Comment thread images/code/scan-secrets
Comment thread internal/scaffold/scaffold_test.go
ascerra added a commit to ascerra/fullsend that referenced this pull request Apr 21, 2026
…aths, hardcoded branch

Resolves all findings from the multi-agent security review.

Critical/High:
- Split single app token into read-only sandbox token
  (contents:read, issues:read, pull_requests:read) and separate
  write-enabled push token. Sandbox can no longer push even if
  disallowedTools is bypassed.
- Add .pre-commit-config.yaml and .gitattributes to protected
  paths — prevents malicious hook injection via agent.
- Replace hardcoded origin/main with TARGET_BRANCH (threaded via
  runner_env, defaults to main). Fixes merge-base, fallback diff,
  and PR --base for non-main repos.

Medium:
- Merge-base fallback now tries origin/TARGET_BRANCH..HEAD before
  HEAD~1 so multi-commit branches are fully checked.
- Replace unquoted variable expansion with mapfile array for
  pre-commit file list (handles spaces/globs safely).
- Remove curl from Vertex AI and gitleaks_releases binary
  allowlists — reduces sandbox attack surface.
- Pin pre-commit==4.5.1 on runner, replace silent || true with
  warning log.
- Bump docker actions: login v4, setup-buildx v4, metadata v6,
  build-push v7.
- Use SHA-tagged base image instead of mutable :latest for
  deterministic agent image builds.
- Replace git commit --amend in SKILL.md with git reset --soft
  HEAD~1 + new commit (amend is blocked by disallowedTools).

Low:
- Add -- separator to git push for branch name safety.
- Add cross-field validation in pre-code.sh (URL repo/number must
  match REPO_FULL_NAME/ISSUE_NUMBER).
- Remove || true from Containerfile pip install — fail fast.
- Add TestScanSecretsImageMatchesScaffold drift test.

Made-with: Cursor
ascerra added a commit to ascerra/fullsend that referenced this pull request Apr 21, 2026
…aths, hardcoded branch

Resolves all findings from the multi-agent security review.

Critical/High:
- Split single app token into read-only sandbox token
  (contents:read, issues:read, pull_requests:read) and separate
  write-enabled push token. Sandbox can no longer push even if
  disallowedTools is bypassed.
- Add .pre-commit-config.yaml and .gitattributes to protected
  paths — prevents malicious hook injection via agent.
- Replace hardcoded origin/main with TARGET_BRANCH (threaded via
  runner_env, defaults to main). Fixes merge-base, fallback diff,
  and PR --base for non-main repos.

Medium:
- Merge-base fallback now tries origin/TARGET_BRANCH..HEAD before
  HEAD~1 so multi-commit branches are fully checked.
- Replace unquoted variable expansion with mapfile array for
  pre-commit file list (handles spaces/globs safely).
- Remove curl from Vertex AI and gitleaks_releases binary
  allowlists — reduces sandbox attack surface.
- Pin pre-commit==4.5.1 on runner, replace silent || true with
  warning log.
- Bump docker actions: login v4, setup-buildx v4, metadata v6,
  build-push v7.
- Use SHA-tagged base image instead of mutable :latest for
  deterministic agent image builds.
- Replace git commit --amend in SKILL.md with git reset --soft
  HEAD~1 + new commit (amend is blocked by disallowedTools).

Low:
- Add -- separator to git push for branch name safety.
- Add cross-field validation in pre-code.sh (URL repo/number must
  match REPO_FULL_NAME/ISSUE_NUMBER).
- Remove || true from Containerfile pip install — fail fast.
- Add TestScanSecretsImageMatchesScaffold drift test.

Made-with: Cursor
@ascerra
ascerra force-pushed the feat/code-agent-scaffold branch from d1033f1 to dce7816 Compare April 21, 2026 02:14
@ascerra ascerra mentioned this pull request Apr 21, 2026

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: Token isolation is silently non-functional — the permission_* inputs use underscores but actions/create-github-app-token@v3 requires hyphens. All four permission inputs are silently ignored, causing the sandbox token to inherit full app installation permissions (including contents:write and pull_requests:write). See inline comment for details and fix.

Comment on lines +72 to +75
permission_contents: read
permission_issues: read
permission_pull_requests: read
permission_metadata: read

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: Permission inputs use wrong delimiter — token isolation is silently broken

These four inputs use underscores (permission_contents) but actions/create-github-app-token@v3 requires hyphens (permission-contents). The permissions are silently ignored, and the sandbox token inherits the full app installation permissions (including contents:write, pull_requests:write).

Evidence chain (verified against action source code):

  1. action.yml defines inputs with hyphens: permission-contents, permission-issues, etc.
  2. GitHub Actions Runner (Handler.cs:AddInputsToEnvironment) creates env vars as INPUT_{key.Replace(' ', '_').ToUpperInvariant()} — only spaces are normalized, underscores/hyphens preserved as-is
  3. Action source (lib/get-permissions-from-inputs.js) scans for key.startsWith("INPUT_PERMISSION-") (hyphen)
  4. Action tests (main-token-permissions-set.test.js) confirm hyphen format: process.env["INPUT_PERMISSION-ISSUES"] = "write"
  5. Action README examples: permission-issues: write

Result: permission_contents → env var INPUT_PERMISSION_CONTENTS (underscore) → does NOT match startsWith("INPUT_PERMISSION-") → permission ignored → token gets full default permissions

Fix:

          permission-contents: read
          permission-issues: read
          permission-pull-requests: read
          permission-metadata: read

Also update TestCodeWorkflowContent assertion to match:

assert.Contains(t, s, "permission-contents: read")

Found independently by 3/4 review agents (Claude Security, Claude Architecture, orchestrator verification). Gemini and Cursor did not catch this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed. Changed all four inputs from underscores to hyphens:

permission-contents: read
permission-issues: read
permission-pull-requests: read
permission-metadata: read

Also updated TestCodeWorkflowContent assertion to match permission-contents: read.

Comment thread internal/scaffold/fullsend-repo/agents/code.md
…aths, hardcoded branch

Resolves all findings from the multi-agent security review.

Critical/High:
- Split single app token into read-only sandbox token
  (contents:read, issues:read, pull_requests:read) and separate
  write-enabled push token. Sandbox can no longer push even if
  disallowedTools is bypassed.
- Add .pre-commit-config.yaml and .gitattributes to protected
  paths — prevents malicious hook injection via agent.
- Replace hardcoded origin/main with TARGET_BRANCH (threaded via
  runner_env, defaults to main). Fixes merge-base, fallback diff,
  and PR --base for non-main repos.

Medium:
- Merge-base fallback now tries origin/TARGET_BRANCH..HEAD before
  HEAD~1 so multi-commit branches are fully checked.
- Replace unquoted variable expansion with mapfile array for
  pre-commit file list (handles spaces/globs safely).
- Remove curl from Vertex AI and gitleaks_releases binary
  allowlists — reduces sandbox attack surface.
- Pin pre-commit==4.5.1 on runner, replace silent || true with
  warning log.
- Bump docker actions: login v4, setup-buildx v4, metadata v6,
  build-push v7.
- Use SHA-tagged base image instead of mutable :latest for
  deterministic agent image builds.
- Replace git commit --amend in SKILL.md with git reset --soft
  HEAD~1 + new commit (amend is blocked by disallowedTools).

Low:
- Add -- separator to git push for branch name safety.
- Add cross-field validation in pre-code.sh (URL repo/number must
  match REPO_FULL_NAME/ISSUE_NUMBER).
- Remove || true from Containerfile pip install — fail fast.
- Add TestScanSecretsImageMatchesScaffold drift test.

Made-with: Cursor

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 14 review findings verified as resolved across 3 review rounds using 4 independent agents (Claude Security, Claude Architecture, Gemini, Cursor).

Critical fixes confirmed:

  • Token isolation: separate read-only sandbox token (permission-contents/issues/pull-requests/metadata: read) and write push token — sandbox token never gets write access
  • Permission delimiter: correctly uses hyphens (permission-contents) matching actions/create-github-app-token@v3 action.yml inputs, with regression test in TestCodeWorkflowContent

Other fixes confirmed:

  • .pre-commit-config.yaml and .gitattributes added to PROTECTED_PATHS
  • TARGET_BRANCH threaded end-to-end (workflow → harness → post-code.sh → PR --base)
  • Array-safe mapfile -t for pre-commit invocation
  • curl/wget removed from network policy binaries
  • Pre-commit pinned ==4.5.1 with ::warning on install failure
  • Docker actions bumped (login@v4, buildx@v4, metadata@v6, build-push@v7)
  • SHA-tagged base image (${{ github.sha }}) in CI pipeline
  • SKILL.md uses git reset --soft HEAD~1 instead of blocked --amend
  • -- separator in git push prevents branch name option injection
  • Cross-field validation in pre-code.sh (URL ↔ REPO_FULL_NAME/ISSUE_NUMBER)
  • Containerfile fails fast on pip errors (removed || true)
  • TestScanSecretsImageMatchesScaffold drift prevention test added

@ascerra
ascerra added this pull request to the merge queue Apr 21, 2026
Merged via the queue into fullsend-ai:main with commit 711cfbf Apr 21, 2026
3 checks passed
@ascerra
ascerra deleted the feat/code-agent-scaffold branch April 21, 2026 15:01
ralphbean added a commit that referenced this pull request Apr 21, 2026
…ox-images

Address review feedback from @ascerra: remove the build-images.yml
workflow (from PR #286) and rename sandbox-image.yml to sandbox-images.yml
to reflect that it builds more than one image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ralphbean ralphbean mentioned this pull request Apr 23, 2026
5 tasks
gbenhaim pushed a commit to gbenhaim/fullsend that referenced this pull request Apr 27, 2026
…aths, hardcoded branch

Resolves all findings from the multi-agent security review.

Critical/High:
- Split single app token into read-only sandbox token
  (contents:read, issues:read, pull_requests:read) and separate
  write-enabled push token. Sandbox can no longer push even if
  disallowedTools is bypassed.
- Add .pre-commit-config.yaml and .gitattributes to protected
  paths — prevents malicious hook injection via agent.
- Replace hardcoded origin/main with TARGET_BRANCH (threaded via
  runner_env, defaults to main). Fixes merge-base, fallback diff,
  and PR --base for non-main repos.

Medium:
- Merge-base fallback now tries origin/TARGET_BRANCH..HEAD before
  HEAD~1 so multi-commit branches are fully checked.
- Replace unquoted variable expansion with mapfile array for
  pre-commit file list (handles spaces/globs safely).
- Remove curl from Vertex AI and gitleaks_releases binary
  allowlists — reduces sandbox attack surface.
- Pin pre-commit==4.5.1 on runner, replace silent || true with
  warning log.
- Bump docker actions: login v4, setup-buildx v4, metadata v6,
  build-push v7.
- Use SHA-tagged base image instead of mutable :latest for
  deterministic agent image builds.
- Replace git commit --amend in SKILL.md with git reset --soft
  HEAD~1 + new commit (amend is blocked by disallowedTools).

Low:
- Add -- separator to git push for branch name safety.
- Add cross-field validation in pre-code.sh (URL repo/number must
  match REPO_FULL_NAME/ISSUE_NUMBER).
- Remove || true from Containerfile pip install — fail fast.
- Add TestScanSecretsImageMatchesScaffold drift test.

Made-with: Cursor
gbenhaim pushed a commit to gbenhaim/fullsend that referenced this pull request Apr 27, 2026
…ox-images

Address review feedback from @ascerra: remove the build-images.yml
workflow (from PR fullsend-ai#286) and rename sandbox-image.yml to sandbox-images.yml
to reflect that it builds more than one image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

3 participants