Skip to content

Test jaswanth #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 6 additions & 0 deletions e2e/test_helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ elif [ -z "$TEST_NAMESPACE" ]; then
echo "Missing TEST_NAMESPACE"
fi

echo "Namespace is $TEST_NAMESPACE"
echo "API key is $DO_API_KEY"

echo "doctl auth list"
doctl auth list

if [ -z "$DOSLS" ]; then
DOSLS=../bin/run
fi
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@digitalocean/functions-deployer",
"version": "5.0.21",
"version": "5.0.22",
"description": "The the functions deployer for DigitalOcean",
"main": "lib/index.js",
"repository": {
Expand Down
38 changes: 21 additions & 17 deletions src/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('validateTriggers', () => {
});
});

describe('encryptProjectConfig', () => {
describe('encryptProjectConfig with AES-GCM', () => {
const yml = `
packages:
- name: test-triggers
Expand All @@ -175,23 +175,27 @@ describe('encryptProjectConfig', () => {
`;

const mockKey =
'cd7a175002a713696fef83b30e93638388eed520eec1cbddec8f51633db3dcb7';
const mockEncryptedData =
'6a0a96cbf2f656a4ec65a9d581a5628d9a5be8abe7910de6cbca8ab4b8e93a63e02a970460871d70f8bc1b773a8eb18b6b270f7e542d2159407ba89559e0477be27fe9c967c5388a7bb10185a5b1247addabe4ce97fb7aa68c034ad2bbfce4c7fcb89bdd7973d46aa215d3489b2ff4fa27523e7ff76ea1845b28010ecccd37c7';

it('should encrypt the project yaml data', () => {
const mockRandomBytes = jest
.spyOn(crypto, 'randomBytes')
.mockImplementationOnce(() => Buffer.from(mockKey, 'hex'));

const res = encryptProjectConfig(yml);
expect(mockRandomBytes).toHaveBeenCalledTimes(1);
expect(res.key).toEqual(mockKey);
expect(res.config).toEqual(mockEncryptedData);
'cd7a175002a713696fef83b30e93638388eed520eec1cbddec8f51633db3dcb7'; // 32 bytes
const mockConfig = `6a0a96cbf2f656a4ec65a9d581a5628d9a5be8abe7910de6cbca8ab4b8e93a63e02a970460871d70f8bc1b773a8eb18b6b270f7e542d2159407ba89559e0477be27fe9c967c5388a7bb10185a5b1247addabe4ce97fb7aa68c034ad2bbfce4c7fcb89bdd7973d46aa215d3489b2ff4fa27523e7ff76ea1845b28010ecccd37c7`;

beforeEach(() => {
jest.restoreAllMocks();
});

it('should decrypt AES-GCM v2 config and return original YAML', () => {
const { config, key } = encryptProjectConfig(yml);

expect(config.startsWith('v2:')).toBe(true);
const parts = config.split(':');
expect(parts.length).toBe(4);

// Decrypt
const decrypted = decryptProjectConfig(config, key);
expect(decrypted).toEqual(yml);
});

it('should decrypt project yaml data given the correct key', () => {
const res = decryptProjectConfig(mockEncryptedData, mockKey);
expect(res).toEqual(yml);
it('should decrypt mock encrypted config and return original YAML', () => {
const decryptedWithOldConfig = decryptProjectConfig(mockConfig, mockKey);
expect(decryptedWithOldConfig).toEqual(yml);
});
});
52 changes: 35 additions & 17 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,45 @@ export function encryptProjectConfig(config: string): {
key: string;
} {
const key = crypto.randomBytes(32);
const iv = Buffer.alloc(16).fill(0);
const cipher = crypto.createCipheriv('aes256', key, iv);
const encrypted = cipher.update(config, 'utf8', 'hex') + cipher.final('hex');
return {
config: encrypted,
key: key.toString('hex')
};
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
const encrypted = Buffer.concat([
cipher.update(config, 'utf8'),
cipher.final()
]);
const authTag = cipher.getAuthTag();
const final = `v2:${iv.toString('hex')}:${authTag.toString(
'hex'
)}:${encrypted.toString('hex')}`;
return { config: final, key: key.toString('hex') };
}

export function decryptProjectConfig(config: string, key: string): string {
const iv = Buffer.alloc(16).fill(0);
const decipher = crypto.createDecipheriv(
'aes256',
Buffer.from(key, 'hex'),
iv
);
const decryptedMessage = Buffer.concat([
decipher.update(config, 'hex'),
export function decryptProjectConfig(
encrypted: string,
keyHex: string
): string {
const key = Buffer.from(keyHex, 'hex');
if (encrypted.startsWith('v2:')) {
const [_v, ivHex, tagHex, encryptedHex] = encrypted.split(':');
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
key,
Buffer.from(ivHex, 'hex')
);
Comment on lines +176 to +180

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
The call to 'createDecipheriv' with the Galois Counter Mode (GCM) mode of operation is missing an expected authentication tag length. If the expected authentication tag length is not specified or otherwise checked, the application might be tricked into verifying a shorter-than-expected authentication tag. This can be abused by an attacker to spoof ciphertexts or recover the implicit authentication key of GCM, allowing arbitrary forgeries.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
key,
Buffer.from(ivHex, 'hex')
);
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
key,
Buffer.from(ivHex, 'hex'),
{ authTagLength: 16 } // Specify the expected authentication tag length in bytes
);
View step-by-step instructions
  1. Pass an additional options object with the authTagLength property set to 16 as the fourth parameter to crypto.createDecipheriv. For example:
    const decipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(ivHex, 'hex'), { authTagLength: 16 });
  2. Make sure that the value for authTagLength matches the length of the authentication tag you use when calling decipher.setAuthTag.
    In AES-GCM, a typical tag length is 16 bytes (128 bits). This helps prevent attackers from supplying shorter authentication tags when decrypting.
  3. Review and update any other instances of createDecipheriv with a GCM mode in your codebase to use the authTagLength option as well.
💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by gcm-no-tag-length.

Questions about this issue? Reach out to Product Security in #prodsec-tools.

You can view more details about this finding in the Semgrep AppSec Platform.

decipher.setAuthTag(Buffer.from(tagHex, 'hex'));
const decrypted = Buffer.concat([
decipher.update(Buffer.from(encryptedHex, 'hex')),
decipher.final()
]);
return decrypted.toString('utf8');
}
const iv = Buffer.alloc(16, 0);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
const decrypted = Buffer.concat([
decipher.update(Buffer.from(encrypted, 'hex')),
decipher.final()
]);
return decryptedMessage.toString('utf8');
return decrypted.toString('utf8');
}

// Rename any 'functions' members of the contained PackageSpecs of a config to 'actions'.
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
// DO NOT EDIT MANUALLY
////////////////////////////////////////////////////////////////

export const version = '5.0.21';
export const version = '5.0.22';
Loading