T09 · Insecure Skill Coding Practices
- Location
scripts/build_index.py:22- Finding
Unrestricted Episode URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a disclosed Simpsons script and character-reference helper, with some normal network and local-cache behavior that users should understand before installing.
Before installing, be comfortable with the skill fetching Simpsons pages from Springfield! Springfield! and caching script data locally. Prefer running it with outbound network limited to that site, and use the character voice helpers as disclosed style-reference tools rather than official-character impersonation or long copyrighted quotation tools.
scripts/build_index.py:22Unrestricted Episode URL Fetching Enables Server-Side Request Forgery
The declared description presents a user-facing Simpsons script search tool focused on locating quotes, identifying episodes, and returning excerpts with source links. The supplied code does not implement search or lookup behavior. Instead, it preprocesses a local corpus to create per-character summary dossiers, including co-occurring terms, related characters, episode counts, sample lines, and candidate catchphrases, and writes them to an output JSON file. While this is Simpsons-related and may support later character comparison features, its primary function is materially different from the declared search/reference purpose, so this is a description-behavior mismatch.
The declared description is about searching Simpsons episode scripts and retrieving quotes or episode references from Springfield! Springfield!. The actual code does something materially different: it looks up a character via a local helper script and outputs a creative-writing brief plus an imitation-style improv prompt. This is not a supporting implementation detail of script search; it is a different primary purpose and relies on different resources. Therefore the description does not accurately represent the behavior of this code chunk.
The declared purpose is an end-user search/reference capability over Simpsons scripts, with source links and optional local indexing. The supplied code does not implement query handling, script search, quote retrieval, or episode identification. Instead, it is a maintenance/data-preparation script that processes a local corpus and character database to generate a new JSON file of character evidence. While tangentially related to Simpsons script data and characters, its primary behavior is materially different from the declared lookup functionality, and it relies on local files rather than the stated Springfield! Springfield! source.
The declared description centers on episode-script and quote search using Springfield! Springfield! as the source, possibly aided by a local episode index. The supplied code does something materially different: it accepts a character name query, loads a local simpsons-characters.json file, fuzzy-matches character names/aliases, and returns structured character-profile data. This is not a supporting detail of script search; it is a separate capability focused on character identification and metadata. Therefore the code chunk does not accurately represent the declared purpose.
The declared description is about searching Simpsons episode scripts and retrieving/referenceing quotes or episode information from a script source. The actual code does not search episode scripts, access Springfield! Springfield!, use a local episode index, identify episodes, return excerpts, or provide source links. Instead, it accepts a character and input text, finds a matching character through another script, and builds a prompt instructing a model to rewrite the text in that character's style. This is a materially different primary purpose and introduces an undeclared capability: character-based dialogue rewriting/generation.
The declared description says this skill searches Simpsons episode scripts and references them as a source for quotes, episode identification, recurring joke/character comparison, and excerpts with links. The supplied code does none of that. It accepts a character name and text/task, calls a local find_character.py helper, optionally reads a local simpsons-character-dossiers.json file, and emits a JSON style guide for generating fresh original dialogue inspired by the character. Its primary purpose is character voice emulation support, not script retrieval or citation. This is a material description-behavior mismatch.
The file implements a character-style rewriting feature that goes beyond the skill's declared purpose of searching and referencing Simpsons scripts. This expands the skill from retrieval into generative impersonation-style content, which creates unnecessary policy, copyright, and misuse risk and increases exposure to prompt abuse without supporting the stated user need.
The skill manifest says the capability is search/reference over Simpsons scripts, but this file constructs a style guide and explicit prompt instructions to generate fresh in-character dialogue. That scope drift can bypass user and platform expectations, enabling impersonation-style content generation and policy evasion through an apparently benign reference skill.
The skill instructs use of file reads/writes, shell commands, and network access but does not declare any tool scope or permission boundaries. That creates an over-privileged, weakly constrained skill surface where an agent may perform broader actions than users would expect, especially when refreshing indexes, fetching remote content, or writing caches.
The quoted example line says to 'Remember everything they say, and tell us later in rattle code,' which is a natural-language instruction to capture others' statements and relay them afterward. Although presented as dialogue content, the semantics describe covert collection and later disclosure without using explicit technical exfiltration terms.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
sys.exit(2)
query = ' '.join(sys.argv[1:]).strip()
proc = subprocess.run(['python3', str(FIND), query], capture_output=True, text=True, check=True)
data = json.loads(proc.stdout)
if not data.get('matches'):
print('No character match found.')
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
character = sys.argv[1]
text = ' '.join(sys.argv[2:]).strip()
proc = subprocess.run(['python3', str(FIND), character], capture_output=True, text=True, check=True)
data = json.loads(proc.stdout)
if not data.get('matches'):
print(json.dumps({'error': 'no character match'}))
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
character = sys.argv[1]
text = ' '.join(sys.argv[2:]).strip()
proc = subprocess.run(['python3', str(FIND), character], capture_output=True, text=True, check=True)
data = json.loads(proc.stdout)
if not data.get('matches'):
print(json.dumps({'error': 'no character match'}))
The inline instructions explicitly direct the model to "write fresh original dialogue inspired by the character," which contradicts the skill's stated reference purpose and operationalizes roleplay generation. In context, this makes the skill more dangerous because it packages generation behavior as a reference helper, increasing the chance of unreviewed character impersonation or misuse.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
correct_top1 = 0
correct_top3 = 0
for item in samples:
proc = subprocess.run(
['python3', str(FIND_QUOTE), item['quote'], '3'],
capture_output=True,
text=True,
This code performs a network request to an external episode URL and downloads remote content, but there is no user-facing notice at the call site about network activity. For code files, outbound HTTP calls that transmit or retrieve data should have some visible disclosure unless clearly covered by the skill description or obviously inherent to the skill's stated purpose; that context is not present in this file.
The script writes fetched episode data into a local cache file, but there is no confirmation, log message, comment, or in-file disclosure indicating that it persists data under the references/cache directory. For code files, file writes should have some form of warning or explanation when they affect user/system data.
No suspicious patterns detected.