fix(web): keep exception text out of calendar responses; annotate moved code

The split made scanners report existing findings in the moved code as new:
- CodeQL: the calendar auth and calendar-list routes returned exception
  text (redacted, but still derived from the exception). Both now log the
  exception and return a fixed message pointing at the log.
- MD5 in the asset upload only makes a filename unique: usedforsecurity=False.
- pickle reads/writes the calendar plugin's own OAuth token (as before):
  annotated. Token-status labels and a log line naming the secrets path are
  false positives: annotated with the repo's nosec/nosemgrep convention.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-28 11:22:24 -04:00
co-authored by Claude Opus 5.5
parent f7bdb24772
commit 5e695b7c39
6 changed files with 23 additions and 19 deletions
@@ -6,7 +6,7 @@ so their endpoint names do not depend on which module they live in.
from web_interface.blueprints.api_v3 import (
Path, _CALENDAR_LIST_MAX_PAGES, _plugin_directory,
_prune_credential_backups, _run_calendar_registration, api_v3,
describe_exception, json, jsonify, logger, os, redact_text, request,
json, jsonify, logger, os, redact_text, request,
shutil,
)
from src.config_manager_atomic import atomic_write_text
@@ -158,29 +158,28 @@ def list_calendar_calendars():
}), 400
try:
import pickle
import pickle # nosec B403 - reads only the plugin's own OAuth token # nosemgrep
from google.auth.transport.requests import Request as GoogleRequest
from googleapiclient.discovery import build as build_google_service
except ImportError as e:
# Which module is missing goes to the log; the exception itself (it
# can quote a path) doesn't go to the client.
logger.warning('Calendar picker: Google API libraries missing: %s', e)
return jsonify({
'status': 'error',
# The name of the missing module is the whole diagnosis, but it
# arrives as an exception, so it goes through the redactor like
# any other -- an ImportError can quote a path.
'message': ('The Google API libraries are not installed. Install '
"the calendar plugin's requirements.txt. (%s)"
% describe_exception(e))
"the calendar plugin's requirements.txt.")
}), 500
with open(token_file, 'rb') as handle:
# Written only by this plugin's own OAuth flow, into its own
# directory, and read here exactly as the plugin itself reads it.
creds = pickle.load(handle) # nosec B301 - locally generated token
creds = pickle.load(handle) # nosec B301 - locally generated token # nosemgrep
if creds and creds.expired and creds.refresh_token:
creds.refresh(GoogleRequest())
with open(token_file, 'wb') as handle:
pickle.dump(creds, handle)
pickle.dump(creds, handle) # nosec B301 - same token, same format # nosemgrep
os.chmod(token_file, 0o600)
if not creds or not creds.valid: