Skip to content

Security defaults: http SSO callbacks in production, and secrets on the importer command line - #8

Merged
krlex merged 2 commits into
developfrom
fix/security-defaults
Aug 19, 2026
Merged

Security defaults: http SSO callbacks in production, and secrets on the importer command line#8
krlex merged 2 commits into
developfrom
fix/security-defaults

Conversation

@krlex

@krlex krlex commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Closes M7 and L2 from the 2026-08-19 Codex review. Two independent
defaults, both about a secret or a scheme leaving the process in a way nobody
chose.

M7 — SSO callbacks could be issued over http in production

SOCIAL_AUTH_REDIRECT_IS_HTTPS was False everywhere. Callback and redirect URLs
are built from the request, and behind a TLS-terminating proxy the request this
process sees is plain HTTP — so the URL handed to the identity provider could
come out as http://. Either the provider rejects it for not matching its
registered redirect URI and SSO breaks, or the exchange completes over an
unprotected scheme with an authorization code in it.

True in the production profile, where TLS terminates in front of this process by
definition. The development default stays False — a dev server speaks plain HTTP
and forcing https makes SSO untestable locally — and that is now written down
rather than implied.

SECURE_PROXY_SSL_HEADER is deliberately not set alongside it. It makes
Django believe any request carrying X-Forwarded-Proto: https, and
PROXY_IP_ALLOWED_LIST is empty by default, so proxy headers are trusted
unconditionally — enabling it without a trusted proxy in front lets a client
assert its own scheme. It belongs in a conf.d override once the proxy is the only
route in; the production settings now spell out the pairing.

L2 — import_from_awx had no unexposed way to pass a secret

--token and --password were the only direct options, and both put a secret in
the process list, in shell history and in process accounting — readable by every
other user on the box for as long as the import runs, which is not brief. The
environment variables helped, but a secret in the environment is still readable
through /proc for the same duration and is inherited by every child.

Adds --token-file and --password-file, and an interactive getpass prompt
when a username is given without a password. Order is file, environment, then the
deprecated flag. The prompt only fires when stdin is a terminal, so a
non-interactive run fails with a usable message instead of blocking on a read
that never returns; missing basic-auth credentials now fail with that message
rather than reaching the API with none.

--token and --password still work, marked DEPRECATED in --help and in the
runtime warning, with removal named as the next breaking release. Taking them
away now would break every automation that calls this — which is what the review
recommends too.

Verified

  • Full standalone matrix green (test_dynamic_survey_standalone.py excepted; it
    cannot be collected on develop at all, which forail-backend#6 fixes).
  • Ruff on the five touched files: 57 findings on this branch, 57 on develop
    — all pre-existing in inherited AWX code, none added here.

krlex added 2 commits August 16, 2026 09:15
`SOCIAL_AUTH_REDIRECT_IS_HTTPS` was False everywhere. SSO callback and redirect
URLs are built from the request, and behind a TLS-terminating proxy the request
this process sees is plain HTTP -- so the URL handed to the identity provider
could come out as `http://`. Either the provider rejects it for not matching its
registered redirect URI and SSO simply breaks, or the exchange completes over an
unprotected scheme with an authorization code in it.

True in the production profile, where TLS terminates in front of this process by
definition. The development default stays False, since a dev server speaks plain
HTTP and forcing https makes SSO untestable locally; that is now written down
rather than implied.

`SECURE_PROXY_SSL_HEADER` is deliberately *not* set alongside it. It makes Django
believe any request carrying `X-Forwarded-Proto: https`, and
`PROXY_IP_ALLOWED_LIST` is empty by default -- proxy headers trusted
unconditionally -- so enabling it without a trusted proxy in front lets a client
assert its own scheme. It belongs in a conf.d override once the proxy is the only
route in, and the production settings now say so with the pairing spelled out.
`--token` and `--password` were the only direct options, and both put a secret
in the process list, in shell history and in process accounting -- readable by
every other user on the box for as long as the import runs, which is not brief.
The environment variables helped, but a secret in the environment is still
readable through /proc for the same duration and is inherited by every child.

Adds `--token-file` and `--password-file`, and an interactive `getpass` prompt
when a username is given without a password. Resolution order is file,
environment, then the deprecated flag; the prompt only fires when stdin is a
terminal, so a non-interactive run fails with a message instead of blocking on a
read that never returns. Missing basic-auth credentials now fail with that
message rather than reaching the API with none.

`--token` and `--password` still work and are marked DEPRECATED in `--help` and
in the runtime warning, with the removal named as the next breaking release --
taking them away now would break every existing automation that calls this.
@krlex
krlex force-pushed the fix/security-defaults branch from 6247ed0 to 2951e67 Compare August 19, 2026 21:17
@krlex
krlex merged commit cfb2827 into develop Aug 19, 2026
3 checks passed
@krlex
krlex deleted the fix/security-defaults branch August 19, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant