Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/codeql-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ name: "Relab CodeQL Config"
queries:
- uses: security-and-quality

# Honor in-code `# codeql[query-id]` / `lgtm[query-id]` suppression comments for
# verified false positives (advanced setup does not include these by default).
# Honor in-code `# lgtm[query-id]` suppression comments for verified false positives
# (advanced setup does not include these queries by default). Write one as a trailing
# comment on the line holding the flagged expression, which for a multi-line call is the
# argument line, not the line that opens the call. The `# codeql[query-id]` spelling is
# matched only when the comment starts its own line, and then covers the line below it.
# See the shared AlertSuppression.qll in github/codeql for both rules.
packs:
python:
- codeql/python-queries:AlertSuppression.ql
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ jobs:

# Code scanning stores but does not act on the suppression data that the
# AlertSuppression queries (see codeql-config.yml) emit for in-code
# `# codeql[query-id]` comments; this official action closes the loop by
# `# lgtm[query-id]` comments; this official action closes the loop by
# dismissing the matching alerts. Suppressions stay reviewable in diffs.
# Default branch only: dismissal is a global alert property, and the action reads
# default-branch alerts only.
Expand Down
20 changes: 14 additions & 6 deletions backend/app/api/auth/services/email/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,25 @@ async def _send_and_log(provider: EmailProvider, message: EmailMessage, log_labe
await provider.send(message)
except Exception:
if attempt == _SEND_ATTEMPTS:
logger.exception( # codeql[py/clear-text-logging-sensitive-data] -- template filename, not a credential
"%s failed for %s after %d attempts", log_label, recipient, attempt
logger.exception(
"%s failed for %s after %d attempts",
log_label, # lgtm[py/clear-text-logging-sensitive-data]
recipient, # lgtm[py/clear-text-logging-sensitive-data]
attempt,
)
return
delay = _SEND_BACKOFF_SECONDS * 2 ** (attempt - 1)
logger.warning( # codeql[py/clear-text-logging-sensitive-data] -- template filename, not a credential
"%s attempt %d failed for %s, retrying in %.1fs", log_label, attempt, recipient, delay, exc_info=True
logger.warning(
"%s attempt %d failed for %s, retrying in %.1fs",
log_label, # lgtm[py/clear-text-logging-sensitive-data]
attempt,
recipient, # lgtm[py/clear-text-logging-sensitive-data]
delay,
exc_info=True,
)
await anyio.sleep(delay)
else:
logger.info("%s sent to %s", log_label, recipient) # codeql[py/clear-text-logging-sensitive-data]
logger.info("%s sent to %s", log_label, recipient) # lgtm[py/clear-text-logging-sensitive-data]
return


Expand All @@ -139,7 +147,7 @@ async def _dispatch(
recipient = email_log_token(to_email)
if background_tasks:
background_tasks.add_task(_send_and_log, provider, message, log_label, recipient)
logger.info("%s queued for %s", log_label, recipient) # codeql[py/clear-text-logging-sensitive-data]
logger.info("%s queued for %s", log_label, recipient) # lgtm[py/clear-text-logging-sensitive-data]
else:
await _send_and_log(provider, message, log_label, recipient)

Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/auth/services/token_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def token_fingerprint(token: str) -> str:
"""Return a stable non-secret fingerprint for auth-token storage keys."""
# Fingerprints high-entropy random bearer tokens (secrets.token_urlsafe), not
# passwords; a slow KDF adds nothing here.
return hashlib.sha256(token.encode("utf-8")).hexdigest() # codeql[py/weak-sensitive-data-hashing]
return hashlib.sha256(token.encode("utf-8")).hexdigest() # lgtm[py/weak-sensitive-data-hashing]


def token_key(key_prefix: str, token: str) -> str:
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/common/rate_limiting.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def hit_key(self, rate_string: str, key: str) -> None:

if not allowed:
# Safe to log: sensitive dimensions arrive as `prefix:<hmac-digest>`, never raw.
logger.info("Rate limit exceeded for bucket %s", key) # codeql[py/clear-text-logging-sensitive-data]
logger.info("Rate limit exceeded for bucket %s", key) # lgtm[py/clear-text-logging-sensitive-data]
raise RateLimitExceededError

def hit_request(self, rate_string: str, request: Request) -> None:
Expand Down
2 changes: 1 addition & 1 deletion backend/app/core/secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def warn_on_placeholder_secrets(logger: logging.Logger, *settings_objects: BaseM
"%s",
rule,
len(offenders),
"\n - ".join(offenders), # codeql[py/clear-text-logging-sensitive-data] -- field NAMES only, never values
"\n - ".join(offenders), # lgtm[py/clear-text-logging-sensitive-data] -- field NAMES only, never values
rule,
)
return offenders
4 changes: 2 additions & 2 deletions scripts/env_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,12 +621,12 @@ def main(argv: list[str] | None = None) -> int:
sys.stdout.write("✅ Environment variable policy checks passed\n")
elif args.command == "inventory":
# Both suppressed writes below emit secret file NAMES from committed config, never values.
sys.stdout.write(format_inventory(load_secret_inventory())) # codeql[py/clear-text-logging-sensitive-data]
sys.stdout.write(format_inventory(load_secret_inventory())) # lgtm[py/clear-text-logging-sensitive-data]
elif args.command == "validation-env":
write_validation_env_file(args.path)
elif args.command == "secrets-list":
for name in compose_secret_names(load_json(args.config)):
sys.stdout.write(f"{name}\n") # codeql[py/clear-text-logging-sensitive-data]
sys.stdout.write(f"{name}\n") # lgtm[py/clear-text-logging-sensitive-data]
elif args.command == "secrets-check":
run_secrets_check(args.configs)
elif args.command == "secrets-placeholder-check":
Expand Down
Loading