Skip to content

security: fail-closed on Twilio webhook auth + drop x-post unpinned auto-install#2000

Open
john-the-dev wants to merge 2 commits into
sonichi:mainfrom
john-the-dev:fix/twilio-webhook-auth-fail-closed
Open

security: fail-closed on Twilio webhook auth + drop x-post unpinned auto-install#2000
john-the-dev wants to merge 2 commits into
sonichi:mainfrom
john-the-dev:fix/twilio-webhook-auth-fail-closed

Conversation

@john-the-dev

Copy link
Copy Markdown
Contributor

Summary

Two confirmed security findings from workspace/notes/security-audit-source-2026-07-06.md:

Finding #2 — Twilio webhook auth fails open (MEDIUM)

validate_twilio_signature in src/agent-api.py returned True when TWILIO_AUTH_TOKEN was unset:

if not auth_token:
    return True  # accepts ALL webhooks unauthenticated

An unauthenticated HTTP POST to /twilio/voice, /twilio/sms, or /twilio/transcription would create a task in the agent without any Twilio signature check. Widened by AGENT_API_BIND=0.0.0.0 (LAN exposure).

Fix: return False — the endpoint requires TWILIO_AUTH_TOKEN to be configured. Adds a 4-test regression suite (tests/agent-api-twilio-auth.test.py).

Finding #5 — x-post unpinned pip auto-install (LOW-MED)

skills/x-twitter/x-post.py ran pip3 install --break-system-packages requests requests-oauthlib as an import side-effect when the packages were missing. Unpinned installs are vulnerable to supply-chain attacks (typosquatting, compromised packages). --break-system-packages overrides OS protection.

Fix: Replace auto-install with sys.exit() printing clear install instructions. Operator installs deps once; the skill never self-modifies the environment.

Test plan

  • python3 tests/agent-api-twilio-auth.test.py — all 4 tests pass
  • CI passes (tsc + tests, coverage gate)
  • Twilio users: set TWILIO_AUTH_TOKEN in .env (was required before; now enforced at the code level too)

🤖 Generated with Claude Code

https://claude.ai/code/session_01QB3qZQrwponfum2JFNvHeh

**Finding sonichi#2 (agent-api.py):** `validate_twilio_signature` returned True
when TWILIO_AUTH_TOKEN was unset, accepting all unauthenticated Twilio
webhooks and allowing arbitrary task injection via /twilio/* endpoints.
Changed to return False — fail closed — with a 4-test regression suite.

**Finding sonichi#5 (skills/x-twitter/x-post.py):** `_require_requests` ran
`pip3 install --break-system-packages` as an import side-effect, exposing
the install to supply-chain attacks on unpinned packages. Replaced with
a clear diagnostic `sys.exit` telling the operator to install the deps
explicitly.

Both findings confirmed in workspace/notes/security-audit-source-2026-07-06.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QB3qZQrwponfum2JFNvHeh
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Coverage Gate

Diff coverage PASSES the 95% bar. Whole-tree (informational): 35%.

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • src/agent-api.py (100%)

Summary

  • Total: 1 line
  • Missing: 0 lines
  • Coverage: 100%

x-post.py no longer auto-installs requests/requests-oauthlib (removed
in the previous commit to eliminate the supply-chain risk from unpinned
pip installs). Document the one-time install step in SKILL.md so operators
know what to run before first use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QB3qZQrwponfum2JFNvHeh
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

@cla-assistant check

@qingyun-wu qingyun-wu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Cold-reviewed — no code defects found.

Twilio fail-closed (src/agent-api.py) — correct. Returning False when TWILIO_AUTH_TOKEN is unset closes the accept-all hole; the 4 regression tests cover no-token / empty-token / missing-sig / wrong-sig. ✅

x-post auto-install drop (skills/x-twitter/x-post.py) — correct hardening; dropping the unpinned --break-system-packages install removes a host-mutation/supply-chain risk. Verified sys is imported (line 21), so the new sys.exit(...) path exits cleanly rather than raising NameError. ✅

Two non-blocking notes:

  1. Operational (before merge): this is a behavior change — any environment running Twilio voice/webhooks without TWILIO_AUTH_TOKEN set will now reject all webhooks. Correct posture, but confirm the token is set in the target .env or phone webhooks stop working. (The docstring already flags this.)
  2. Scope: two concerns in one PR (Twilio auth + x-post install). Both from the same 07-06 audit and small, so not worth splitting — just noting per single-concern-per-PR.

No blockers from me; recommend merge after confirming (1). Merge stays your call.

@john-the-dev john-the-dev marked this pull request as ready for review July 8, 2026 14:37
@qingyun-wu

Copy link
Copy Markdown
Collaborator

Automated mergeability review (2026-07-09)

Signal: NOT MERGEABLE

Current blocker(s):

  • Branch is behind current main; update/merge main and rerun checks before merging.

This is a conservative backlog triage signal. After the blockers are cleared, please rerun checks and request a focused review.

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.

2 participants