New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

tangerine

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tangerine - npm Package Compare versions

Comparing version 1.4.6 to 1.4.7

113

index.js

@@ -23,3 +23,2 @@ const dns = require('node:dns');

const structuredClone = require('@ungap/structured-clone').default;
const { Hosts } = require('hosts-parser');
const { getService } = require('port-numbers');

@@ -31,9 +30,2 @@

const hosts = new Hosts(
hostile
.get()
.map((arr) => arr.join(' '))
.join('\n')
);
// dynamically import dohdec

@@ -46,4 +38,28 @@ let dohdec;

// dynamically import private-ip
let isPrivateIP;
// eslint-disable-next-line unicorn/prefer-top-level-await
import('private-ip').then((obj) => {
isPrivateIP = obj.default;
});
const HOSTFILE = hostile
.get(true)
.map((s) => (Array.isArray(s) ? s.join(' ') : s))
.join('\n');
const HOSTS = [];
const hosts = hostile.get();
for (const line of hosts) {
const [ip, str] = line;
const hosts = str.split(' ');
HOSTS.push({ ip, hosts });
}
// <https://github.com/szmarczak/cacheable-lookup/pull/76>
class Tangerine extends dns.promises.Resolver {
static HOSTFILE = HOSTFILE;
static HOSTS = HOSTS;
static isValidPort(port) {

@@ -622,2 +638,12 @@ return Number.isSafeInteger(port) && port >= 0 && port <= 65535;

if (name === '.') {
const err = this.constructor.createError(name, '', dns.NOTFOUND);
// remap and perform syscall
err.syscall = 'getaddrinfo';
err.message = err.message.replace('query', 'getaddrinfo');
err.errno = -3008; // <-- ?
// err.errno = -3007;
throw err;
}
// purge cache support

@@ -669,21 +695,18 @@ let purgeCache;

// sorted in reverse to match behavior of lookup
for (const rule of hosts._origin.reverse()) {
if (
rule.hostname.toLowerCase() !== name.toLowerCase() &&
rule.ip !== name
)
continue;
const lower = name.toLowerCase();
for (const rule of this.constructor.HOSTS) {
if (rule.hosts.every((h) => h.toLowerCase() !== lower)) continue;
const type = isIP(rule.ip);
if (!resolve4 && type === 4) resolve4 = [rule.ip];
else if (!resolve6 && type === 6) resolve6 = [rule.ip];
if (resolve4 && resolve6) break;
if (!resolve4 && type === 4) {
if (!Array.isArray(resolve4)) resolve4 = [rule.ip];
else if (!resolve4.includes(rule.ip)) resolve4.push([rule.ip]);
} else if (!resolve6 && type === 6) {
if (!Array.isArray(resolve6)) resolve6 = [rule.ip];
else if (!resolve6.includes(rule.ip)) resolve6.push(rule.ip);
}
}
// if no matches found for resolve4 and resolve6 and it was localhost
// (this is a safeguard in case host file is missing these)
if (
name.toLowerCase() === 'localhost' ||
name.toLowerCase() === 'localhost.'
) {
// safeguard (matches c-ares)
if (lower === 'localhost' || lower === 'localhost.') {
if (!resolve4) resolve4 = ['127.0.0.1'];

@@ -741,21 +764,2 @@ if (!resolve6) resolve6 = ['::1'];

/*
//
// NOTE: we probably should handle this differently (?)
// (not sure what native nodejs dns module does for different errors - haven't checked yet)
//
if (errors.every((e) => e.code !== 'ENODATA')) {
const err = this.constructor.combineErrors(errors);
err.hostname = name;
// remap and perform syscall
err.syscall = 'getaddrinfo';
err.message = err.message.replace('query', 'getaddrinfo');
if (!err.code)
err.code = errors.find((e) => e.code)?.code || dns.BADRESP;
if (!err.errno)
err.errno = errors.find((e) => e.errno)?.errno || undefined;
throw err;
}
*/
// default node behavior seems to return IPv4 by default always regardless

@@ -936,5 +940,22 @@ if (answers.length > 0)

// edge case where localhost IP returns empty
if (ip === '127.0.0.1' || ip === '::1') return [];
// edge case where localhost IP returns matches
if (!isPrivateIP) await pWaitFor(() => Boolean(isPrivateIP));
const answers = new Set();
let match = false;
for (const rule of this.constructor.HOSTS) {
if (rule.ip === ip) {
match = true;
for (const host of rule.hosts.slice(1)) {
answers.add(host);
}
}
}
if (answers.size > 0 || match) return [...answers];
// NOTE: we can prob remove this (?)
// if (ip === '::1' || ip === '127.0.0.1') return [];
// reverse the IP address

@@ -1440,3 +1461,3 @@ if (!dohdec) await pWaitFor(() => Boolean(dohdec));

// <https://github.com/c-ares/c-ares/blob/38b30bc922c21faa156939bde15ea35332c30e08/src/lib/ares_getaddrinfo.c#L829>
if (name.startsWith('.') || name.includes('..'))
if (name !== '.' && (name.startsWith('.') || name.includes('..')))
throw this.constructor.createError(name, rrtype, dns.BADNAME);

@@ -1443,0 +1464,0 @@

{
"name": "tangerine",
"description": "Tangerine is the best Node.js drop-in replacement for dns.promises.Resolver using DNS over HTTPS (\"DoH\") via undici with built-in retries, timeouts, smart server rotation, AbortControllers, and caching support for multiple backends (with TTL and purge support).",
"version": "1.4.6",
"version": "1.4.7",
"author": "Forward Email (https://forwardemail.net)",

@@ -19,3 +19,2 @@ "bugs": {

"hostile": "^1.3.3",
"hosts-parser": "^0.3.2",
"ipaddr.js": "^2.0.1",

@@ -27,2 +26,3 @@ "merge-options": "3.0.4",

"port-numbers": "^6.0.1",
"private-ip": "^3.0.0",
"punycode": "^2.3.0",

@@ -46,2 +46,3 @@ "semver": "^7.3.8"

"ioredis-mock": "^8.2.6",
"is-ci": "^3.0.1",
"lint-staged": "^13.1.2",

@@ -48,0 +49,0 @@ "lodash": "^4.17.21",

@@ -61,2 +61,3 @@ <h1 align="center">

* [Cache](#cache)
* [Compatibility](#compatibility)
* [Debugging](#debugging)

@@ -434,2 +435,11 @@ * [Benchmarks](#benchmarks)

## Compatibility
The only known compatibility issue is for locally running DNS servers that have wildcard DNS matching.
If you are using `dnsmasq` with a wildcard match on "localhost" to "127.0.0.1", then the results may vary. For example, if your `dnsmasq` configuration has `address=/localhost/127.0.0.1`, then any match of `localhost` will resolve to `127.0.0.1`. This means that `dns.promises.lookup('foo.localhost')` will return `127.0.0.1` – however with :tangerine: Tangerine it will not return a value.
The reason is because :tangerine: Tangerine only looks at either `/etc/hosts` (macOS/Linux) and `C:/Windows/System32/drivers/etc/hosts` (Windows). It does not lookup BIND, dnsmasq, or other configurations running locally. We would welcome a PR to resolve this (see `isCI` usage in test folder) – however it is a non-issue, as the workaround is to simply append a new line to the hostfile of `127.0.0.1 foo.localhost`.
## Debugging

@@ -436,0 +446,0 @@

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