Socket
Socket
Sign inDemoInstall

packageurl-js

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

packageurl-js - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# 1.0.1
### Bug Fixes
* Hardened encoding/decoding of URL special chars like `@` and `#` [#37](https://github.com/package-url/packageurl-js/pull/37)
# 1.0.0

@@ -2,0 +6,0 @@ ### Features

2

package.json
{
"name": "packageurl-js",
"version": "1.0.0",
"version": "1.0.1",
"description": "JavaScript library to parse and build \"purl\" aka. package URLs. This is a microlibrary implementing the purl spec at https://github.com/package-url",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -79,3 +79,3 @@ /*!

toString() {
var purl = ['pkg:', this.type, '/'];
var purl = ['pkg:', encodeURIComponent(this.type), '/'];

@@ -95,7 +95,7 @@ if (this.type === 'pypi') {

purl.push(encodeURIComponent(this.name).replace('%3A', ':'));
purl.push(encodeURIComponent(this.name).replace(/%3A/g, ':'));
if (this.version) {
purl.push('@');
purl.push(encodeURIComponent(this.version).replace('%3A', ':'));
purl.push(encodeURIComponent(this.version).replace(/%3A/g, ':'));
}

@@ -109,3 +109,7 @@

Object.keys(qualifiers).sort().forEach(key => {
qualifierString.push(encodeURIComponent(key).replace('%3A', ':') + '=' + encodeURI(qualifiers[key]));
qualifierString.push(
encodeURIComponent(key).replace(/%3A/g, ':')
+ '='
+ encodeURIComponent(qualifiers[key]).replace(/%2F/g, '/')
);
});

@@ -118,3 +122,5 @@

purl.push('#');
purl.push(encodeURI(this.subpath));
purl.push(encodeURIComponent(this.subpath)
.replace(/%3A/g, ':')
.replace(/%2F/g, '/'));
}

@@ -126,3 +132,3 @@

static fromString(purl) {
if (!purl || !typeof purl === 'string' || !purl.trim()) {
if (!purl || typeof purl !== 'string' || !purl.trim()) {
throw new Error('A purl string argument is required.');

@@ -144,2 +150,3 @@ }

}
type = decodeURIComponent(type)

@@ -159,5 +166,5 @@ let url = new URL(purl);

}
if (subpath.length === 0) {
subpath = null;
}
subpath = subpath.length === 0
? null
: decodeURIComponent(subpath)

@@ -164,0 +171,0 @@ if (url.username !== '' || url.password !== '') {

@@ -24,2 +24,4 @@ /*!

const assert = require('assert');
const {describe, it} = require("mocha");
const TEST_FILE = require('./data/test-suite-data.json');

@@ -31,2 +33,21 @@

describe('PackageURL', function () {
describe('toString()', function () {
it('all components encode #', function () {
/* The # is a delimiter between url and subpath. */
var purl = new PackageURL('ty#pe', 'name#space', 'na#me', 'ver#sion', {'foo':'bar#baz'}, 'sub#path');
assert.strictEqual(purl.toString(), 'pkg:ty%23pe/name%23space/na%23me@ver%23sion?foo=bar%23baz#sub%23path')
})
it('all components encode @', function () {
/* The @ is a delimiter between package name and version. */
var purl = new PackageURL('ty@pe', 'name@space', 'na@me', 'ver@sion', {'foo':'bar@baz'}, 'sub@path');
assert.strictEqual(purl.toString(), 'pkg:ty%40pe/name%40space/na%40me@ver%40sion?foo=bar%40baz#sub%40path')
})
it('path components encode /', function () {
/* only namespace is allowed to have multiple segments separated by `/`` */
var purl = new PackageURL('ty/pe', 'namespace1/namespace2', 'na/me');
assert.strictEqual(purl.toString(), 'pkg:ty%2Fpe/namespace1/namespace2/na%2Fme')
})
})
describe('fromString()', function () {

@@ -60,2 +81,29 @@ it('with qualifiers.checksums', function () {

});
it('namespace with multiple segments', function () {
var purl = PackageURL.fromString('pkg:ty%2Fpe/namespace1/namespace2/na%2Fme')
assert.strictEqual('ty/pe', purl.type)
assert.strictEqual('namespace1/namespace2', purl.namespace)
assert.strictEqual('na/me', purl.name)
})
it('encoded #', function () {
var purl = PackageURL.fromString('pkg:ty%23pe/name%23space/na%23me@ver%23sion?foo=bar%23baz#sub%23path')
assert.strictEqual('ty#pe', purl.type)
assert.strictEqual('name#space', purl.namespace)
assert.strictEqual('na#me', purl.name)
assert.strictEqual('ver#sion', purl.version)
assert.deepStrictEqual({foo:'bar#baz'}, purl.qualifiers)
assert.strictEqual('sub#path', purl.subpath)
})
it('encoded @', function () {
var purl = PackageURL.fromString('pkg:ty%40pe/name%40space/na%40me@ver%40sion?foo=bar%40baz#sub%40path')
assert.strictEqual('ty@pe', purl.type)
assert.strictEqual('name@space', purl.namespace)
assert.strictEqual('na@me', purl.name)
assert.strictEqual('ver@sion', purl.version)
assert.deepStrictEqual({foo:'bar@baz'}, purl.qualifiers)
assert.strictEqual('sub@path', purl.subpath)
})
});

@@ -71,3 +119,3 @@

} catch (e) {
assert.equal(true, e.toString().includes('is a required field') || e.toString().includes('Invalid purl'));
assert.ok(e.toString().includes('is a required field') || e.toString().includes('Invalid purl'));
}

@@ -79,3 +127,3 @@ });

} catch (e) {
assert.equal(true, e.toString().includes('Error: purl is missing the required') || e.toString().includes('Invalid purl'));
assert.ok(e.toString().includes('Error: purl is missing the required') || e.toString().includes('Invalid purl'));
}

@@ -86,22 +134,22 @@ });

var purl = new PackageURL(obj.type, obj.namespace, obj.name, obj.version, obj.qualifiers, obj.subpath);
assert.equal(obj.type, purl.type);
assert.equal(obj.name, purl.name);
assert.equal(obj.namespace, purl.namespace);
assert.equal(obj.version, purl.version);
assert.equal(JSON.stringify(obj.qualifiers), JSON.stringify(purl.qualifiers));
assert.equal(obj.subpath, purl.subpath);
assert.strictEqual(purl.type, obj.type);
assert.strictEqual(purl.name, obj.name);
assert.strictEqual(purl.namespace, obj.namespace);
assert.strictEqual(purl.version, obj.version);
assert.deepStrictEqual(purl.qualifiers, obj.qualifiers);
assert.strictEqual(purl.subpath, obj.subpath, );
});
it('should be able to convert valid PackageURLs to a string', function () {
var purl = new PackageURL(obj.type, obj.namespace, obj.name, obj.version, obj.qualifiers, obj.subpath);
assert.equal(obj.canonical_purl, purl.toString());
assert.strictEqual(purl.toString(), obj.canonical_purl);
});
it('should be able to parse valid PackageURLs', function () {
var purl = PackageURL.fromString(obj.canonical_purl);
assert.equal(purl.toString(), obj.canonical_purl);
assert.equal(purl.type, obj.type);
assert.equal(purl.name, obj.name);
assert.equal(purl.namespace, obj.namespace);
assert.equal(purl.version, obj.version);
assert.equal(JSON.stringify(purl.qualifiers), JSON.stringify(obj.qualifiers));
assert.equal(purl.subpath, obj.subpath);
assert.strictEqual(purl.toString(), obj.canonical_purl);
assert.strictEqual(purl.type, obj.type);
assert.strictEqual(purl.name, obj.name);
assert.strictEqual(purl.namespace, obj.namespace);
assert.strictEqual(purl.version, obj.version);
assert.deepStrictEqual(purl.qualifiers, obj.qualifiers);
assert.strictEqual(purl.subpath, obj.subpath);
});

@@ -108,0 +156,0 @@ it('should handle pypi package-urls per the purl-spec', function () {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc