T05 · Unauthorized Access and Privilege Escalation
- Location
SKILL.md:40- Finding
Unauthenticated Exposure of Household State on All Network Interfaces
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a coherent local TV dashboard controller, but it exposes and renders sensitive household state in ways users should review before installing.
Install only if you are comfortable with a local household dashboard storing reminders, room notes, patterns, and optional precise coordinates in earl_mind.json. Before use, bind the server to 127.0.0.1, avoid exposing port 8000 to other devices, use approximate coordinates or disable weather if privacy matters, and do not let untrusted messages or web content write into the state file until the dashboard escapes or sanitizes rendered fields. Back up earl_mind.json before using clear/reset helper methods, and verify the target process before running any force-kill command.
SKILL.md:40Unauthenticated Exposure of Household State on All Network Interfaces
VisuoSpatialSketchpad/sketchpad.html:803Stored DOM Cross-Site Scripting Through Unescaped Dashboard State
The description partially matches the content-update portion of the code: it can update Earl's mood, house stuff, hot takes, sketchpad, and room/spatial state by modifying a local JSON file. However, several prominent declared capabilities are not implemented at all in this code chunk, especially the operational TV/dashboard management actions (wake display, restart server, launch kiosk browser) and weather updates. Conversely, the code includes additional capabilities not mentioned in the description, such as setting Earl's photo and recording long-term patterns. Because the declared purpose emphasizes broader TV dashboard management beyond what this code actually does, this is a material description-behavior mismatch.
The declared description presents a broad TV dashboard management skill with multiple operational actions and general content-updating capabilities. The supplied code chunk instead performs one narrow file-editing task: it reorders a single hard-coded 'hot take' entry in earl_mind.json. While this is loosely related to 'hot takes,' the actual behavior is much narrower and materially different from the declared primary purpose. It neither manages the display/server/browser nor generally updates dashboard state; it only reprioritizes one specific item in stored data.
The description presents a broader TV dashboard management skill, including operational actions on the display/server/browser and general updates to several dashboard sections. This code chunk performs only narrow local data mutation in earl_mind.json. It does support part of the declared domain by updating house stuff and a hot take-like section, but it omits the major advertised behaviors and instead makes specific hard-coded edits plus an extra reset of long_term_patterns. Therefore the supplied code does not accurately represent the declared description.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
cp VisuoSpatialSketchpad/earl_mind.template.json VisuoSpatialSketchpad/earl_mind.json
The skill documents capabilities to read and write persistent dashboard data and to fetch network data, but it does not declare any explicit tool scope or permissions boundary. This increases the chance that an agent executes file or network actions without least-privilege controls or clear operator review, especially because the skill encourages direct JSON mutation and external weather fetching.
The skill instructs use of forceful process-termination commands such as kill -9 and Stop-Process -Force without requiring validation of the target process or warning about collateral termination. In an agentic setting, this can disrupt unrelated services, cause data loss, or be misapplied if port ownership or process selection is wrong.
The skill explicitly instructs direct mutation and manual editing of a persisted JSON state file without emphasizing that these changes are durable and can alter live dashboard behavior. This creates risk of accidental corruption, unauthorized content changes, or integrity issues if an agent writes malformed or unintended data to the file.
The clear_house_stuff method deletes all house-stuff items and immediately persists the change via save(), but there is no confirmation prompt or user-facing disclosure at the point of deletion. Although the docstring names the action, the operation is irreversible within this API and lacks any stronger warning about bulk data removal.
The clear_sketchpad method removes all sketchpad canvas entries and immediately writes the updated state to disk. While the docstring says 'Wipe the sketchpad clean,' there is no confirmation step, user-visible log, or stronger warning that this is a destructive persisted action.
The script silently removes a hard-coded 'hot take' entry from Earl's persisted state, which does not match the declared display-control/dashboard-management purpose of the skill. In a skill expected to update or display information, undisclosed deletion of content is risky because it can tamper with user data, hide information, or serve as covert behavior inconsistent with the manifest.
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
break
if match is not None:
takes.insert(0, takes.pop(match))
path.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding='utf-8')
print(f"Moved '{TARGET}' to top")
else:
print(f"Take '{TARGET}' not found")
The page builds a third-party weather request using precise latitude, longitude, and timezone from local state and sends it to api.open-meteo.com without any user-facing disclosure or consent flow. In a home-dashboard context, that leaks household location metadata to an external service and can expose sensitive occupancy or residence information.
This code transmits location-derived query parameters to an external domain over the network. Although the destination is a legitimate weather API and HTTPS is used, the security concern is the unnecessary exposure of household coordinates and related metadata to a third party from a domestic display-control skill.
const unit = loc.temperature_unit || 'fahrenheit';
const wind = loc.wind_speed_unit || 'mph';
const tz = loc.timezone || 'America/New_York';
return `https://api.open-meteo.com/v1/forecast?latitude=${loc.latitude}&longitude=${loc.longitude}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_max,weather_code&temperature_unit=${unit}&windspeed_unit=${wind}&timezone=${tz}&forecast_days=4`;
}
const WMO_CODES = {
This code overwrites the JSON file on disk via path.write_text(...), which is a safety-relevant data modification. The file contains no confirmation prompt, logging/print statement, docstring, or comment disclosing that it will persistently change earl_mind.json.
This script writes the modified mind object back to earl_mind.json, replacing prior contents for several sections including house_stuff and long_term_patterns. There is no confirmation prompt, logging, comment, or docstring warning the user that running the script will alter persisted data.
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
mind["long_term_patterns"] = []
mind["meta"]["last_updated"] = datetime.datetime.utcnow().isoformat()
mind["meta"]["update_count"] = mind["meta"].get("update_count", 0) + 1
mind_path.write_text(json.dumps(mind, indent=2, ensure_ascii=False), encoding='utf-8')
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
path = Path('earl_mind.json')
mind = json.loads(path.read_text(encoding='utf-8'))
mind['identity']['current_vibe'] = 'Text me on Telegram to add stuff.'
path.write_text(json.dumps(mind, indent=2, ensure_ascii=False), encoding='utf-8')
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
path = Path('earl_mind.json')
mind = json.loads(path.read_text(encoding='utf-8'))
mind['identity']['current_vibe'] = 'Text me on Telegram to add stuff.'
path.write_text(json.dumps(mind, indent=2, ensure_ascii=False), encoding='utf-8')
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
path = Path('earl_mind.json')
mind = json.loads(path.read_text(encoding='utf-8'))
mind['identity']['current_vibe'] = 'Text me on Telegram to add stuff.'
path.write_text(json.dumps(mind, indent=2, ensure_ascii=False), encoding='utf-8')
The script constructs a weather API request using latitude, longitude, and timezone read from a local mind file, which discloses precise location data to a third-party service. In this skill context, the data appears functionally necessary for weather retrieval, but there is no minimization, consent, or indication that household location is being transmitted externally, creating a privacy leak of sensitive home-location metadata.
This code makes an outbound HTTPS request to api.open-meteo.com and includes precise latitude and longitude in the query string. The transmission is not inherently malicious, but in a home-dashboard skill the context increases sensitivity because it can expose the physical location of a residence to an external provider and to logs, caches, or monitoring systems that capture URLs.
_house_name = _mind_data.get("spatial_awareness", {}).get("house_name", "the house")
URL = (
f"https://api.open-meteo.com/v1/forecast?latitude={_lat}&longitude={_lon}"
f"¤t=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,wind_speed_10m"
f"&temperature_unit={_temp_unit}&windspeed_unit={_wind_unit}&timezone={_tz}"
)
This markdown file tells users to populate latitude and longitude for their house, which is sensitive location data. Although the README later mentions that the live state file contains real household state, the setup instructions themselves do not warn users that entering exact coordinates exposes private location information.
The configuration sets "timezone" to "America/New_York", "temperature_unit" to "fahrenheit", and "wind_speed_unit" to "mph". This imposes a specific locale and unit convention in natural-language/config values without any indication of user opt-in or that the skill is intentionally region-specific.
The fallback message tells users "I auto-wake by restarting the server + reloading this page," implying this page performs server restart behavior. In this file, the implemented behavior is limited to fetching local JSON and weather data on intervals; there is no code that restarts any server or triggers a wake action.
The weather configuration defaults to fahrenheit, mph, and America/New_York, which bakes in a specific regional locale when user preferences are absent. This can violate language/locale policy expectations because the file does not offer user choice or clearly justify the U.S.-centric defaults.
No suspicious patterns detected.