feat: add regex validation to role-session-name (#1765)

Previously invalid role session names would get errors from the STS
API instead of this action rejecting them, causing unnecessary retries.
Now we check them and fail early.

Closes #1656. That FR recommended that we sanitize the name before
sending to STS, but instead we error to not silently change the user's
selected session name (avoiding the potential security sharp edge)
This commit is contained in:
Tom Keller
2026-05-11 14:32:33 -07:00
committed by GitHub
parent 958a80fc34
commit e35449909c
3 changed files with 44 additions and 0 deletions
Generated Vendored
+11
View File
@@ -72805,6 +72805,7 @@ function writeProfileFiles(profileName, credentials, region, overwriteAwsProfile
var DEFAULT_ROLE_DURATION = 3600;
var ROLE_SESSION_NAME = "GitHubActions";
var REGION_REGEX = /^[a-z0-9-]+$/g;
var ROLE_SESSION_NAME_REGEX = /^[\w+=,.@-]*$/;
async function run() {
try {
translateEnvVariables();
@@ -72878,6 +72879,16 @@ async function run() {
if (!region.match(REGION_REGEX)) {
throw new Error(`Region is not valid: ${region}`);
}
if (roleSessionName.length < 2 || roleSessionName.length > 64) {
throw new Error(
`Role session name must be between 2 and 64 characters, got ${roleSessionName.length}: '${roleSessionName}'`
);
}
if (!roleSessionName.match(ROLE_SESSION_NAME_REGEX)) {
throw new Error(
`Role session name is not valid: '${roleSessionName}'. Must satisfy regular expression pattern: [\\w+=,.@-]*`
);
}
exportRegion(region, outputEnvCredentials);
const clientProps = {
region,
+12
View File
@@ -19,6 +19,7 @@ import { writeProfileFiles } from './profileManager';
const DEFAULT_ROLE_DURATION = 3600; // One hour (seconds)
const ROLE_SESSION_NAME = 'GitHubActions';
const REGION_REGEX = /^[a-z0-9-]+$/g;
const ROLE_SESSION_NAME_REGEX = /^[\w+=,.@-]*$/;
export async function run() {
try {
@@ -129,6 +130,17 @@ export async function run() {
throw new Error(`Region is not valid: ${region}`);
}
if (roleSessionName.length < 2 || roleSessionName.length > 64) {
throw new Error(
`Role session name must be between 2 and 64 characters, got ${roleSessionName.length}: '${roleSessionName}'`,
);
}
if (!roleSessionName.match(ROLE_SESSION_NAME_REGEX)) {
throw new Error(
`Role session name is not valid: '${roleSessionName}'. Must satisfy regular expression pattern: [\\w+=,.@-]*`,
);
}
exportRegion(region, outputEnvCredentials);
// Instantiate credentials client
+21
View File
@@ -351,6 +351,27 @@ describe('Configure AWS Credentials', {}, () => {
await run();
expect(core.setFailed).toHaveBeenCalled();
});
it('fails with a role-session-name containing invalid characters', {}, async () => {
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({ ...mocks.IAM_ASSUMEROLE_INPUTS, 'role-session-name': 'invalid session!' }),
);
await run();
expect(core.setFailed).toHaveBeenCalledWith(expect.stringContaining('Role session name is not valid'));
});
it('fails with a role-session-name that is too short', {}, async () => {
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({ ...mocks.IAM_ASSUMEROLE_INPUTS, 'role-session-name': 'a' }),
);
await run();
expect(core.setFailed).toHaveBeenCalledWith(expect.stringContaining('must be between 2 and 64 characters'));
});
it('fails with a role-session-name that is too long', {}, async () => {
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({ ...mocks.IAM_ASSUMEROLE_INPUTS, 'role-session-name': 'a'.repeat(65) }),
);
await run();
expect(core.setFailed).toHaveBeenCalledWith(expect.stringContaining('must be between 2 and 64 characters'));
});
it('fails if access key id is provided without secret access key', {}, async () => {
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({ ...mocks.IAM_USER_INPUTS, 'aws-secret-access-key': '' }),