Files
ai-workflow-course/modules/15-security-scanning/lab/config.py
T
claude f925fd9645 fix(M7-27+capstone): apply AI-drives-git reframe, lesson=theory, de-slop course-wide
Phase 2 sweep — all modules are post-pivot, so the learner directs the AI agent
(Claude Code as the worked example) to do the git/setup work and verifies, instead
of typing commands by hand; no re-teaching basics. Lesson sections are theory with
example output; all execution lives in the labs. De-slopped ("prose" etc. gone
course-wide, em-dash density thinned). /path/to placeholders -> ~/ai-workflow-course.

Every deliberate teaching device verified intact: M10 ai-change.patch trap,
M12 bad-clear-snippet, M13/M27 planted pending_count bug, M15 secret+typosquat+MD5,
M18 BREAK=1, M21 absent-.gitignore, M22 poisoned skill, M24 no-op patch, M25 --simulate.
Labs compile/parse (py/sh/yaml/json); no junk.

Closes #83
Closes #86
Closes #89

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TfzV5QvtPDz8LJS3Pu5VLT
2026-06-22 21:58:17 -04:00

40 lines
2.0 KiB
Python

"""Cloud-sync config for tasks-app — a realistic snapshot of what an AI hands you.
Asked to "sync tasks to a cloud service," a model will produce something like this: it works, it
reads naturally, it passes lint and tests... and it carries two planted flaws: a live credential
baked straight into the source (caught by Gate 2, secret scanning) and a weak-crypto "signature"
using MD5 (caught by Gate 3, SAST). Two different gates, two different blind spots.
DO NOT copy these patterns. The point of this file is to be caught by a scanner, not imitated.
The fix (read from the environment) is shown at the bottom, commented out, so you can see the
difference once Part C of the lab is done.
"""
import hashlib
# --- The problem the SECRET scanner should flag (Gate 2) ---------------------------------------
# A hardcoded API key. Looks like a normal string literal; lint and tests will never complain.
SYNC_API_KEY = "sk_live_9c3f2a7b41d84e0fa6b2c5d8e1f09a73bdac46"
SYNC_ENDPOINT = "https://api.example-task-cloud.com/v1/sync"
def sync_headers() -> dict:
return {"Authorization": f"Bearer {SYNC_API_KEY}"}
# --- The problem the SAST scanner should flag (Gate 3) -----------------------------------------
# AI-classic: "sign" the request body with a quick hash. MD5 is broken for anything
# security-relevant — a textbook weak-crypto idiom. A secret scanner won't catch this (it's not a
# secret); a SAST tool like bandit will (it's insecure code you wrote). DO NOT imitate.
def sign_payload(body: str) -> str:
return hashlib.md5(body.encode()).hexdigest()
# --- The fix (Part C) --------------------------------------------------------------------------
# Read the secret from the environment instead of committing it. Proper secret management — env
# files, secret stores, per-environment config — is Module 17. This is just enough to make the
# scanner go quiet honestly.
#
# import os
# SYNC_API_KEY = os.environ["SYNC_API_KEY"] # set it outside the repo; never commit the value