GitHub Actions OIDC AWS error: trust policy
En pocas palabras: El AccessDenied ocurre en sts:AssumeRoleWithWebIdentity, antes de que AWS emita la sesión, así que es un problema de trust policy (proveedor OIDC, audience y claim sub), no de permisos IAM como s3:* o cloudformation:*. Ampliar permisos no arregla nada si la identidad no supera ese control previo.
Un job de GitHub Actions falla al intentar asumir un rol de AWS por OIDC, con un error de autorización que ocurre antes de tocar cualquier servicio de AWS. El diagnóstico más común (ampliar permisos del rol IAM) no soluciona nada, porque el problema real está en la trust policy, no en los permisos, según detalla este análisis publicado en Dev.to.
El error GitHub Actions OIDC AWS error más frecuente es AssumeRoleWithWebIdentity: AccessDenied. Es una decisión de identidad y confianza que AWS STS evalúa antes de emitir la sesión del rol, y por lo tanto antes de que aplique cualquier permission policy. Distinguir esto de un AccessDenied posterior (ya con la sesión activa) es la clave para no perder tiempo tocando lo que no corresponde.
En este artículo:
- En 30 segundos
- ¿Qué diferencia hay entre un error de trust policy y uno de permission policy en AWS?
- ¿Cómo se identifica la firma del error cuando falla la asunción de rol por OIDC?
- ¿Qué inputs de confianza revisa AWS al validar el token OIDC de GitHub Actions?
- ¿Cómo afecta el formato de subject inmutable de GitHub (desde julio 2026) a las trust policies existentes?
- Por qué ampliar los permisos del rol de IAM no soluciona el AccessDenied de OIDC
- ¿Cuál es la secuencia de diagnóstico correcta para un error de trust policy en OIDC?
- ¿Cómo se corrige la trust policy paso a paso?
- Errores comunes al configurar OIDC entre GitHub Actions y AWS
- Preguntas Frecuentes
- Conclusión
- Fuentes
En 30 segundos
- El error ocurre en
sts:AssumeRoleWithWebIdentity, antes de que la sesión reciba permisos del rol. - Ampliar permisos IAM (s3:*, cloudformation:*) no resuelve nada si el fallo es de trust policy.
- Los tres inputs clave son el proveedor OIDC, el claim
aud(normalmentests.amazonaws.com) y el claimsubexacto. - Desde el 15 de julio de 2026, los repos nuevos de GitHub usan un formato de
subinmutable con IDs de owner y repo. - Un rename o transfer de repo también migra al formato inmutable y puede romper una trust policy vieja.
¿Qué diferencia hay entre un error de trust policy y uno de permission policy en AWS?
Un error de trust policy pasa cuando AWS todavía no confía en la identidad que le presentás, mientras que un error de permission policy pasa cuando AWS ya confió en vos pero no te dejó hacer algo puntual. La trust policy del rol define quién puede pedir AssumeRoleWithWebIdentity; la permission policy define qué puede hacer esa sesión una vez que ya la tiene.
Son dos capas completamente distintas. Si alguna vez armaste un rol de IAM para GitHub Actions, seguramente te topaste con esto: el workflow ni siquiera llega a ejecutar el aws s3 cp o el aws cloudformation deploy, se cae antes, en el paso de configure-aws-credentials. Eso es una señal clarísima de que el problema no está en lo que el rol puede hacer, sino en quién puede convertirse en ese rol. Esto se conecta con lo que analizamos en los checks de seguridad esenciales en AWS.
¿Cómo se identifica la firma del error cuando falla la asunción de rol por OIDC?

La firma es simple: el workflow llega al paso de asumir el rol y ahí mismo corta, con un error de autorización, sin haber llamado a ningún servicio de AWS todavía. Nunca aparece el aws sts get-caller-identity exitoso, nunca hay logs de S3 ni de CloudFormation. Todo se rompe en ese primer handshake.
Esto contrasta con un caso distinto: el rol se asume bien, la sesión queda activa, y recién ahí una llamada a un servicio (ponele, un PutObject en S3) devuelve AccessDenied. Ese segundo caso sí es un problema de permission policy. Confundir estas dos firmas es lo que lleva a la gente a tocar el permission policy cuando el problema real está más atrás, en el trust.
¿Qué inputs de confianza revisa AWS al validar el token OIDC de GitHub Actions?
AWS valida tres cosas antes de emitir la sesión: el proveedor OIDC federado (token.actions.githubusercontent.com), el claim aud (normalmente sts.amazonaws.com con la action oficial configure-aws-credentials) y el claim sub, que identifica exactamente de dónde viene el workflow.
El sub es el que más dolores de cabeza genera porque cambia según el contexto. Un job disparado por push a una rama tiene un subject tipo repo:org/repo:ref:refs/heads/main; un job que usa un GitHub Environment tiene un subject orientado a ese ambiente, del tipo repo:org/repo:environment:prod. Si copiaste un ejemplo de trust policy de un tutorial que usaba branch y tu job usa Environment (o al revés), la condición StringEquals nunca va a matchear, por más que el resto esté perfecto. Para más detalles técnicos, mirá nuestra base consultable de errores de GitHub Actions.
¿Cómo afecta el formato de subject inmutable de GitHub (desde julio 2026) a las trust policies existentes?
Desde el 15 de julio de 2026, los repositorios creados en GitHub usan por defecto un formato de sub inmutable que incluye los IDs numéricos de owner y repositorio, según confirma la documentación oficial de GitHub sobre OIDC con AWS. Los repos creados antes de esa fecha siguen con el formato basado en nombre, salvo que hayas optado explícitamente por el nuevo.
Ojo con esto: un rename o un transfer de repositorio también dispara la migración al formato inmutable, aunque el repo sea viejo. El formato pasa de repo:octo-org/octo-repo:ref:refs/heads/main a algo como repo:octo-org@123456/octo-repo@456789:ref:refs/heads/main. Si tu trust policy tiene el subject hardcodeado con el formato anterior, un rename silencioso puede tumbar un deploy en producción sin que nadie haya tocado el pipeline. Para repos de vida larga, conviene dejar registrado qué formato de subject usa cada uno, así un rename no se convierte en sorpresa.
Por qué ampliar los permisos del rol de IAM no soluciona el AccessDenied de OIDC
Agregar s3:*, cloudformation:* u otro permiso al rol no puede arreglar una decisión de trust fallida, porque esos permisos solo se activan después de que AWS ya emitió la sesión. Si el fallo ocurre en AssumeRoleWithWebIdentity, la sesión ni siquiera existe todavía.
¿Y qué pasa si igual amplías permisos “por las dudas”? Nada bueno. El error sigue igual (la sesión nunca se emite) y el rol queda con más privilegio del necesario, esperando el día que alguien sí logre asumirlo. Es el peor de los dos mundos: no resolvés el bug y agrandás la superficie de ataque. Relacionado: desplegar con Docker Compose a EC2.
¿Cuál es la secuencia de diagnóstico correcta para un error de trust policy en OIDC?
La secuencia recomendada por la fuente analizada tiene seis pasos, en orden, y recién en el último se mira permisos de servicio:
- Confirmar el permission del token. El job o el workflow debe tener
permissions: id-token: writedeclarado. - Confirmar que existe el proveedor OIDC en la cuenta de AWS. Tiene que estar dado de alta para
token.actions.githubusercontent.com. - Confirmar que la trust policy nombra ese proveedor. El
Principal.Federateddebe apuntar al ARN correcto del OIDC provider. - Confirmar que la condición
audcoincide. Normalmentests.amazonaws.comsi usás la action oficial. - Confirmar que la condición
subcoincide con el formato actual del repo y el contexto del job. Acá es donde más falla la gente, por el tema branch/environment/formato inmutable. - Recién después, diagnosticar permisos de servicio. Solo si el rol se asume bien y el error aparece más tarde, en una llamada puntual a un servicio.
¿Cómo se corrige la trust policy paso a paso?
La corrección mínima es mantener la trust policy acotada y hacer que sus condiciones matcheen la identidad real del workflow, no un ejemplo copiado. La estructura genérica, según el repositorio oficial de aws-actions/configure-aws-credentials, es esta:
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "<GITHUB_SUBJECT>"
}
}
}El <GITHUB_SUBJECT> es un placeholder a propósito. Tenés que sacarlo del modo de subject que usa tu repo actualmente y del contexto exacto del job: si corre en un GitHub Environment protegido, la trust policy debería alinearse con ese environment, y las reglas de protección del ambiente suman una capa de control extra. Con un preflight de identidad (asumir el rol y correr un aws sts get-caller-identity, sin tocar nada más) podés validar la capa de trust antes de dejar que el workflow ejecute cualquier deploy real.
Errores comunes al configurar OIDC entre GitHub Actions y AWS
- Copiar el subject de un tutorial sin adaptarlo. El ejemplo suele usar un branch fijo; tu job puede correr en un Environment, en un pull request, o en un repo con formato inmutable.
- Ampliar permisos como primer reflejo. Si el error es en
AssumeRoleWithWebIdentity, ningún permiso adicional cambia el resultado. - No registrar el formato de subject por repositorio. Un rename o transfer puede migrar al formato inmutable sin aviso y romper la trust policy en producción.
- Usar
StringLikecon wildcard sin necesidad. Sirve para permitir cualquier branch o environment de un repo, pero también amplía quién puede asumir el rol; conviene reservarlo para casos donde de verdad hace falta esa flexibilidad.
Preguntas Frecuentes
¿Por qué GitHub Actions no puede asumir el rol de AWS con OIDC?
Casi siempre porque la trust policy del rol no matchea la identidad real del token OIDC que envía GitHub, ya sea por el claim aud, por el sub o porque el proveedor OIDC no está dado de alta en la cuenta de AWS. El permission policy del rol no interviene en esta etapa. Más contexto en la comparativa de herramientas CI/CD 2026.
¿Cómo se soluciona el error AssumeRoleWithWebIdentity AccessDenied?
Se soluciona ajustando la trust policy, no los permisos: hay que verificar que el proveedor OIDC federado, el aud y el sub coincidan exactamente con el contexto del workflow que intenta asumir el rol.
¿Qué diferencia hay entre un error de trust policy y uno de permisos en AWS?
El error de trust policy ocurre antes de obtener la sesión del rol, en AssumeRoleWithWebIdentity. El error de permisos ocurre después, cuando la sesión ya existe y una llamada puntual a un servicio de AWS devuelve AccessDenied.
¿Qué formato de claim sub usa GitHub Actions para OIDC con AWS?
Depende de la fecha de creación del repositorio y del contexto del job: repos creados antes del 15 de julio de 2026 usan un formato basado en nombre (repo:org/repo:ref:refs/heads/branch), mientras que los repos nuevos o que optaron por el cambio usan un formato inmutable con IDs numéricos de owner y repo.
¿Por qué agregar permisos a mi rol de IAM no resuelve el error de OIDC?
Porque los permisos del rol solo aplican después de que AWS emitió la sesión, y el error de OIDC ocurre antes de ese paso. Ampliar permisos no cambia la evaluación de la trust policy, solo agrega privilegio innecesario a un rol que todavía no se puede asumir.
Conclusión
El GitHub Actions OIDC AWS error de tipo AccessDenied casi siempre se resuelve mirando la trust policy, no el permission policy. Antes de tocar un solo permiso IAM, conviene confirmar el id-token: write, el proveedor OIDC, y sobre todo que el sub coincida con el contexto real del job, branch, pull request o Environment. Con el cambio al formato inmutable desde julio de 2026, vale la pena revisar qué formato de subject usa cada repositorio antes de que un rename inesperado te rompa un deploy. Si administrás infraestructura propia además de pipelines en AWS, en donweb.com podés resolver hosting y dominios locales sin salir de la región.






